| # Copyright 2016 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import logging |
| import os |
| from autotest_lib.client.bin import utils |
| from autotest_lib.client.common_lib import error |
| from autotest_lib.client.cros import service_stopper |
| from autotest_lib.client.cros.graphics import graphics_utils |
| |
| |
| class DrmTest(object): |
| |
| def __init__(self, name, command=None, **kargs): |
| """ |
| @param name(str) |
| @param command(str): The shell command to run. If None, then reuse 'name'. |
| @param kargs: Test options |
| """ |
| |
| self._opts = { |
| 'timeout': 20, |
| 'display_required': True, |
| 'vulkan_required': False, |
| 'min_kernel_version': None |
| } |
| self._opts.update(kargs) |
| self.name = name |
| self._command = command |
| if self._command is None: |
| self._command = name |
| |
| def can_run(self): |
| """Indicate if the test can be run on the configuration.""" |
| num_displays = graphics_utils.get_num_outputs_on() |
| if num_displays == 0 and utils.get_device_type() == 'CHROMEBOOK': |
| # Sanity check to guard against incorrect silent passes. |
| logging.error('Error: found Chromebook without display.') |
| return False |
| return True |
| |
| def should_run(self): |
| """Indicate if the test should be run on current configuration.""" |
| supported_apis = graphics_utils.GraphicsApiHelper().get_supported_apis() |
| num_displays = graphics_utils.get_num_outputs_on() |
| gpu_type = utils.get_gpu_family() |
| soc = utils.get_cpu_soc_family() |
| kernel_version = os.uname()[2] |
| if num_displays == 0 and self._opts['display_required']: |
| # If a test needs a display and we don't have a display, |
| # consider it a pass. |
| logging.warning('No display connected, skipping test.') |
| return False |
| if self._opts['vulkan_required'] and 'vk' not in supported_apis: |
| # If a test needs vulkan to run and we don't have it, |
| # consider it a pass |
| logging.warning('Vulkan is required by test but is not ' |
| 'available on system. Skipping test.') |
| return False |
| if self._opts['min_kernel_version']: |
| min_kernel_version = self._opts['min_kernel_version'] |
| if utils.compare_versions(kernel_version, min_kernel_version) < 0: |
| logging.warning('Test requires kernel version >= %s,' |
| 'have version %s. Skipping test.' |
| % (min_kernel_version, kernel_version)) |
| return False |
| if self.name == 'atomictest' and gpu_type == 'baytrail': |
| logging.warning('Baytrail is on kernel v4.4, but there is no ' |
| 'intention to enable atomic.') |
| return False |
| return True |
| |
| def run(self): |
| try: |
| # TODO(pwang): consider TEE to another file if drmtests keep |
| # spewing so much output. |
| cmd_result = utils.run( |
| self._command, |
| timeout=self._opts['timeout'], |
| stderr_is_expected=True, |
| verbose=True, |
| stdout_tee=utils.TEE_TO_LOGS, |
| stderr_tee=utils.TEE_TO_LOGS |
| ) |
| logging.info('Passed: %s', self._command) |
| logging.debug('Duration: %s: (%0.2fs)' |
| % (self._command, cmd_result.duration)) |
| return True |
| except error.CmdTimeoutError as e: |
| logging.error('Failed: Timeout while running %s (timeout=%0.2fs)' |
| % (self._command, self._opts['timeout'])) |
| logging.debug(e) |
| return False |
| except error.CmdError as e: |
| logging.error('Failed: %s (exit=%d)' % (self._command, |
| e.result_obj.exit_status)) |
| logging.debug(e) |
| return False |
| except Exception as e: |
| logging.error('Failed: Unexpected exception while running %s' |
| % self._command) |
| logging.debug(e) |
| return False |
| |
| drm_tests = { |
| test.name: test |
| for test in ( |
| DrmTest('atomictest', 'atomictest -t all', min_kernel_version='4.4', |
| timeout=300), |
| DrmTest('drm_cursor_test'), |
| DrmTest('linear_bo_test'), |
| DrmTest('mmap_test', timeout=300), |
| DrmTest('null_platform_test'), |
| DrmTest('swrast_test', display_required=False), |
| DrmTest('vgem_test', display_required=False), |
| DrmTest('vk_glow', vulkan_required=True), |
| ) |
| } |
| |
| class graphics_Drm(graphics_utils.GraphicsTest): |
| """Runs one, several or all of the drm-tests.""" |
| version = 1 |
| _services = None |
| |
| def initialize(self): |
| super(graphics_Drm, self).initialize() |
| self._services = service_stopper.ServiceStopper(['ui']) |
| self._services.stop_services() |
| |
| def cleanup(self): |
| if self._services: |
| self._services.restore_services() |
| super(graphics_Drm, self).cleanup() |
| |
| # graphics_Drm runs all available tests if tests = None. |
| def run_once(self, tests=None, perf_report=False): |
| self._test_failure_report_enable = perf_report |
| self._test_failure_report_subtest = perf_report |
| for test in drm_tests.itervalues(): |
| if tests and test.name not in tests: |
| continue |
| |
| logging.info('-----------------[%s]-----------------' % test.name) |
| self.add_failures(test.name, subtest=test.name) |
| passed = False |
| if test.should_run(): |
| if test.can_run(): |
| logging.debug('Running test %s.', test.name) |
| passed = test.run() |
| else: |
| logging.info('Failed: test %s can not be run on current' |
| ' configurations.' % test.name) |
| else: |
| passed = True |
| logging.info('Skipping test: %s.' % test.name) |
| |
| if passed: |
| self.remove_failures(test.name, subtest=test.name) |
| |
| if self.get_failures(): |
| raise error.TestFail('Failed: %s' % self.get_failures()) |