| # Copyright (c) 2012 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 |
| import time |
| |
| from autotest_lib.client.bin import test |
| from autotest_lib.client.bin import utils as bin_utils |
| from autotest_lib.client.common_lib import error, utils |
| from autotest_lib.client.cros.graphics import graphics_utils |
| |
| # to run this test manually on a test target |
| # ssh root@machine |
| # cd /usr/local/autotest/tests/graphics_GpuReset/src/ |
| # stop ui |
| # ./gpureset |
| # start ui |
| |
| |
| class graphics_GpuReset(graphics_utils.GraphicsTest): |
| """ |
| Reset the GPU and check recovery mechanism. |
| """ |
| version = 1 |
| preserve_srcdir = True |
| loops = 1 |
| |
| def setup(self): |
| os.chdir(self.srcdir) |
| utils.make('clean') |
| utils.make('all') |
| |
| def initialize(self): |
| # GpuReset should pretty much be the only test where we don't want to raise |
| # a test error when we detect a GPU hang. |
| super(graphics_GpuReset, self).initialize(raise_error_on_hang=False) |
| |
| def cleanup(self): |
| super(graphics_GpuReset, self).cleanup() |
| |
| @graphics_utils.GraphicsTest.failure_report_decorator('graphics_GpuReset') |
| def run_once(self, options=''): |
| gpu_family = bin_utils.get_gpu_family() |
| if gpu_family == 'stoney': |
| options = '-s 7 -t 1' |
| exefile = 'amdgpu_test' |
| else: |
| options = '' |
| exefile = os.path.join(self.srcdir, 'gpureset') |
| if not os.path.isfile(exefile): |
| raise error.TestFail('Failed: could not locate gpureset executable (' + |
| exefile + ').') |
| |
| cmd = '%s %s' % (exefile, options) |
| |
| # If UI is running, we must stop it and restore later. |
| need_restart_ui = False |
| status_output = utils.system_output('initctl status ui') |
| # If chrome is running, result will be similar to: |
| # ui start/running, process 11895 |
| logging.info('initctl status ui returns: %s', status_output) |
| need_restart_ui = status_output.startswith('ui start') |
| summary = '' |
| |
| # Run the gpureset test in a loop to stress the recovery. |
| for i in range(1, self.loops + 1): |
| summary += 'graphics_GpuReset iteration %d of %d\n' % (i, self.loops) |
| if need_restart_ui: |
| summary += 'initctl stop ui\n' |
| utils.system('initctl stop ui', ignore_status=True) |
| # TODO(ihf): Remove this code if no improvement for issue 409019. |
| logging.info('Make sure chrome is dead before triggering hang.') |
| utils.system('killall -9 chrome', ignore_status=True) |
| time.sleep(3) |
| try: |
| summary += utils.system_output(cmd, retain_output=True) |
| summary += '\n' |
| finally: |
| if need_restart_ui: |
| summary += 'initctl start ui\n' |
| utils.system('initctl start ui') |
| |
| # Write a copy of stdout to help debug failures. |
| results_path = os.path.join(self.outputdir, 'summary.txt') |
| f = open(results_path, 'w+') |
| f.write('# need ui restart: %s\n' % need_restart_ui) |
| f.write('# ---------------------------------------------------\n') |
| f.write('# [' + cmd + ']\n') |
| f.write(summary) |
| f.write('\n# -------------------------------------------------\n') |
| f.write('# [graphics_GpuReset.py postprocessing]\n') |
| |
| # Analyze the output. Sample: |
| # [ OK ] graphics_GpuReset |
| # [ FAILED ] graphics_GpuReset |
| results = summary.splitlines() |
| if not results: |
| f.close() |
| raise error.TestFail('Failed: No output from test. Check /tmp/' + |
| 'test_that_latest/graphics_GpuReset/summary.txt' + |
| ' for details.') |
| # Analyze summary and count number of passes. |
| pass_count = 0 |
| for line in results: |
| if gpu_family == 'stoney': |
| if "passed" in line: |
| pass_count += 1 |
| if "failed" in line: |
| raise error.TestFail('Failed: %s' % line) |
| else: |
| if line.strip().startswith('[ OK ] graphics_GpuReset'): |
| pass_count += 1 |
| if line.strip().startswith('[ FAILED ] graphics_GpuReset'): |
| msg = line.strip()[30:] |
| failed_msg = 'Test failed with %s' % msg |
| raise error.TestFail('Failed: %s' % failed_msg) |
| f.close() |
| |
| # Final chance to fail. |
| if pass_count != self.loops: |
| failed_msg = 'Test failed with incomplete output. System hung? ' |
| failed_msg += '(pass_count=%d of %d)' % (pass_count, self.loops) |
| raise error.TestFail('Failed: %s' % failed_msg) |
| |
| # We need to wait a bit for X to come back after the 'start ui'. |
| time.sleep(5) |