1# Copyright (c) 2012 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 5import logging 6import os 7import time 8 9from autotest_lib.client.bin import test 10from autotest_lib.client.common_lib import error, utils 11from autotest_lib.client.cros.graphics import graphics_utils 12 13# to run this test manually on a test target 14# ssh root@machine 15# cd /usr/local/autotest/tests/graphics_GpuReset/src/ 16# stop ui 17# ./gpureset 18# start ui 19 20 21class graphics_GpuReset(test.test): 22 """ 23 Reset the GPU and check recovery mechanism. 24 """ 25 version = 1 26 preserve_srcdir = True 27 loops = 1 28 GSC = None 29 30 def setup(self): 31 os.chdir(self.srcdir) 32 utils.make('clean') 33 utils.make('all') 34 35 def initialize(self): 36 # GpuReset should pretty much be the only test where we don't want to raise 37 # a test error when we detect a GPU hang. 38 self.GSC = graphics_utils.GraphicsStateChecker(raise_error_on_hang=False) 39 40 def cleanup(self): 41 if self.GSC: 42 self.GSC.finalize() 43 44 def run_once(self, options=''): 45 exefile = os.path.join(self.srcdir, 'gpureset') 46 if not os.path.isfile(exefile): 47 raise error.TestFail('Failed to locate gpureset executable (' + 48 exefile + '). Test setup error.') 49 50 options = '' 51 cmd = '%s %s' % (exefile, options) 52 53 # If UI is running, we must stop it and restore later. 54 need_restart_ui = False 55 status_output = utils.system_output('initctl status ui') 56 # If chrome is running, result will be similar to: 57 # ui start/running, process 11895 58 logging.info('initctl status ui returns: %s', status_output) 59 need_restart_ui = status_output.startswith('ui start') 60 summary = '' 61 62 # Run the gpureset test in a loop to stress the recovery. 63 for i in range(1, self.loops + 1): 64 summary += 'graphics_GpuReset iteration %d of %d\n' % (i, self.loops) 65 if need_restart_ui: 66 summary += 'initctl stop ui\n' 67 utils.system('initctl stop ui', ignore_status=True) 68 # TODO(ihf): Remove this code if no improvement for issue 409019. 69 logging.info('Make sure chrome is dead before triggering hang.') 70 utils.system('killall -9 chrome', ignore_status=True) 71 time.sleep(3) 72 try: 73 summary += utils.system_output(cmd, retain_output=True) 74 summary += '\n' 75 finally: 76 if need_restart_ui: 77 summary += 'initctl start ui\n' 78 utils.system('initctl start ui') 79 80 # Write a copy of stdout to help debug failures. 81 results_path = os.path.join(self.outputdir, 'summary.txt') 82 f = open(results_path, 'w+') 83 f.write('# need ui restart: %s\n' % need_restart_ui) 84 f.write('# ---------------------------------------------------\n') 85 f.write('# [' + cmd + ']\n') 86 f.write(summary) 87 f.write('\n# -------------------------------------------------\n') 88 f.write('# [graphics_GpuReset.py postprocessing]\n') 89 90 # Analyze the output. Sample: 91 # [ OK ] graphics_GpuReset 92 # [ FAILED ] graphics_GpuReset 93 results = summary.splitlines() 94 if not results: 95 f.close() 96 raise error.TestFail('No output from test. Check /tmp/' + 97 'test_that_latest/graphics_GpuReset/summary.txt' + 98 ' for details.') 99 # Analyze summary and count number of passes. 100 pass_count = 0 101 for line in results: 102 if line.strip().startswith('[ OK ] graphics_GpuReset'): 103 pass_count += 1 104 if line.strip().startswith('[ FAILED ] graphics_GpuReset'): 105 msg = line.strip()[30:] 106 failed_msg = 'Test failed with %s' % msg 107 raise error.TestFail(failed_msg) 108 f.close() 109 110 # Final chance to fail. 111 if pass_count != self.loops: 112 failed_msg = 'Test failed with incomplete output. System hung? ' 113 failed_msg += '(pass_count=%d of %d)' % (pass_count, self.loops) 114 raise error.TestFail(failed_msg) 115 116 # We need to wait a bit for X to come back after the 'start ui'. 117 time.sleep(5) 118 119 keyvals = self.GSC.get_memory_keyvals() 120 for key, val in keyvals.iteritems(): 121 self.output_perf_value(description=key, value=val, units='bytes', 122 higher_is_better=False) 123