| # 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 glob |
| import logging |
| import os |
| import time |
| |
| from autotest_lib.client.bin import test |
| from autotest_lib.client.bin import utils |
| from autotest_lib.client.common_lib import error |
| from autotest_lib.client.common_lib.cros import chrome |
| from autotest_lib.client.cros.graphics import graphics_utils |
| from autotest_lib.client.cros.image_comparison import pdiff_image_comparer |
| from autotest_lib.client.cros.input_playback import input_playback |
| |
| def get_percent_difference(file1, file2): |
| """ |
| Performs pixel comparison of two files, given by their paths |file1| |
| and |file2| using terminal tool 'perceptualdiff' and returns percentage |
| difference of the total file size. |
| |
| @param file1: path to image |
| @param file2: path to secondary image |
| @return: percentage difference of total file size. |
| @raise ValueError: if image dimensions are not the same |
| @raise OSError: if file does not exist or cannot be opened. |
| |
| """ |
| # Using pdiff image comparer to compare the two images. This class |
| # invokes the terminal tool perceptualdiff. |
| pdi = pdiff_image_comparer.PdiffImageComparer() |
| diff_bytes = pdi.compare(file1, file2)[0] |
| return round(100. * diff_bytes / os.path.getsize(file1)) |
| |
| |
| class graphics_VTSwitch(test.test): |
| """ |
| Verify that VT switching works. |
| """ |
| version = 2 |
| GSC = None |
| _WAIT = 5 |
| # TODO(crosbug.com/36417): Need to handle more than one display screen. |
| |
| def initialize(self): |
| self.GSC = graphics_utils.GraphicsStateChecker() |
| self._player = input_playback.InputPlayback() |
| self._player.emulate(input_type='keyboard') |
| self._player.find_connected_inputs() |
| |
| def _open_vt2(self): |
| """Use keyboard shortcut to open VT2.""" |
| self._player.blocking_playback_of_default_file( |
| input_type='keyboard', filename='keyboard_ctrl+alt+f2') |
| time.sleep(self._WAIT) |
| |
| def _open_vt1(self): |
| """Use keyboard shortcut to close VT2.""" |
| self._player.blocking_playback_of_default_file( |
| input_type='keyboard', filename='keyboard_ctrl+alt+f1') |
| time.sleep(self._WAIT) |
| |
| def run_once(self, |
| num_iterations=2, |
| similarity_percent_threshold=95, |
| difference_percent_threshold=5): |
| |
| # Check for chromebook type devices |
| if not utils.get_board_type() == 'CHROMEBOOK': |
| raise error.TestNAError('DUT is not Chromebook. Test Skipped.') |
| |
| self._num_errors = 0 |
| keyvals = {} |
| |
| # Make sure we start in VT1. |
| self._open_vt1() |
| |
| with chrome.Chrome(): |
| |
| # Take screenshot of browser. |
| vt1_screenshot = self._take_current_vt_screenshot(1) |
| |
| keyvals['num_iterations'] = num_iterations |
| |
| # Go to VT2 and take a screenshot. |
| self._open_vt2() |
| vt2_screenshot = self._take_current_vt_screenshot(2) |
| |
| # Make sure VT1 and VT2 are sufficiently different. |
| diff = get_percent_difference(vt1_screenshot, vt2_screenshot) |
| keyvals['percent_initial_VT1_VT2_difference'] = diff |
| if not diff >= difference_percent_threshold: |
| self._num_errors += 1 |
| logging.error('VT1 and VT2 screenshots only differ by ' + \ |
| '%d %%: %s vs %s' % |
| (diff, vt1_screenshot, vt2_screenshot)) |
| |
| num_identical_vt1_screenshots = 0 |
| num_identical_vt2_screenshots = 0 |
| max_vt1_difference_percent = 0 |
| max_vt2_difference_percent = 0 |
| |
| # Repeatedly switch between VT1 and VT2. |
| for iteration in xrange(num_iterations): |
| logging.info('Iteration #%d', iteration) |
| |
| # Go to VT1 and take a screenshot. |
| self._open_vt1() |
| current_vt1_screenshot = self._take_current_vt_screenshot(1) |
| |
| # Make sure the current VT1 screenshot is the same as (or similar |
| # to) the original login screen screenshot. |
| diff = get_percent_difference(vt1_screenshot, |
| current_vt1_screenshot) |
| if not diff < similarity_percent_threshold: |
| max_vt1_difference_percent = \ |
| max(diff, max_vt1_difference_percent) |
| self._num_errors += 1 |
| logging.error('VT1 screenshots differ by %d %%: %s vs %s', |
| diff, vt1_screenshot, |
| current_vt1_screenshot) |
| else: |
| num_identical_vt1_screenshots += 1 |
| |
| # Go to VT2 and take a screenshot. |
| self._open_vt2() |
| current_vt2_screenshot = self._take_current_vt_screenshot(2) |
| |
| # Make sure the current VT2 screenshot is the same as (or |
| # similar to) the first VT2 screenshot. |
| diff = get_percent_difference(vt2_screenshot, |
| current_vt2_screenshot) |
| if not diff <= similarity_percent_threshold: |
| max_vt2_difference_percent = \ |
| max(diff, max_vt2_difference_percent) |
| self._num_errors += 1 |
| logging.error( |
| 'VT2 screenshots differ by %d %%: %s vs %s', |
| diff, vt2_screenshot, current_vt2_screenshot) |
| else: |
| num_identical_vt2_screenshots += 1 |
| |
| self._open_vt1() |
| |
| keyvals['percent_VT1_screenshot_max_difference'] = \ |
| max_vt1_difference_percent |
| keyvals['percent_VT2_screenshot_max_difference'] = \ |
| max_vt2_difference_percent |
| keyvals['num_identical_vt1_screenshots'] = num_identical_vt1_screenshots |
| keyvals['num_identical_vt2_screenshots'] = num_identical_vt2_screenshots |
| |
| self.write_perf_keyval(keyvals) |
| |
| if self._num_errors > 0: |
| raise error.TestFail('Failed: saw %d VT switching errors.' % |
| self._num_errors) |
| |
| def _take_current_vt_screenshot(self, current_vt): |
| """ |
| Captures a screenshot of the current VT screen in BMP format. |
| |
| @param current_vt: desired vt for screenshot. |
| |
| @returns the path of the screenshot file. |
| |
| """ |
| extension = 'bmp' |
| |
| # In VT1, X is running so use that screenshot function. |
| if current_vt == 1: |
| return graphics_utils.take_screenshot(self.resultsdir, |
| 'graphics_VTSwitch_VT1', |
| extension) |
| |
| # Otherwise, take a screenshot using screenshot.py. |
| prefix = 'graphics_VTSwitch_VT2' |
| next_index = len(glob.glob( |
| os.path.join(self.resultsdir, '%s-*.%s' % (prefix, extension)))) |
| filename = '%s-%d.%s' % (prefix, next_index, extension) |
| output_path = os.path.join(self.resultsdir, filename) |
| return self._take_screenshot(output_path) |
| |
| def _take_screenshot(self, output_path): |
| """ |
| Takes screenshot. |
| |
| @param output_path: screenshot output path. |
| |
| @returns output_path where screenshot was saved. |
| |
| """ |
| screenshot_path = os.path.join(self.autodir, 'bin', 'screenshot.py') |
| utils.system('%s %s' % (screenshot_path, output_path), |
| ignore_status=True) |
| utils.system('sync', ignore_status=True) |
| time.sleep(self._WAIT) |
| logging.info('Saving screenshot to %s', output_path) |
| return output_path |
| |
| def cleanup(self): |
| # Return to VT1 when done. Ideally, the screen should already be in VT1 |
| # but the test might fail and terminate while in VT2. |
| self._open_vt1() |
| if self.GSC: |
| self.GSC.finalize() |
| self._player.close() |