1# Copyright (c) 2010 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 os
6import logging
7
8from autotest_lib.client.bin import utils
9from autotest_lib.client.common_lib import error
10from autotest_lib.client.common_lib.cros import chrome
11from autotest_lib.client.cros import service_stopper
12from autotest_lib.client.cros.graphics import graphics_utils
13
14# to run this test manually on a test target
15# ssh root@machine
16# cd /usr/local/glbench/bin
17# stop ui
18# ./windowmanagertest --screenshot1_sec 2 --screenshot2_sec 1 --cooldown_sec 1 \
19#    --screenshot1_cmd "screenshot screenshot1_generated.png" \
20#    --screenshot2_cmd "screenshot screenshot2_generated.png"
21# start ui
22
23
24class graphics_Sanity(graphics_utils.GraphicsTest):
25    """
26    This test is meant to be used as a quick sanity check for GL/GLES.
27    """
28    version = 1
29
30    # None-init vars used by cleanup() here, in case setup() fails
31    _services = None
32
33    def cleanup(self):
34        super(graphics_Sanity, self).cleanup()
35        if self._services:
36            self._services.restore_services()
37
38    def test_something_on_screen(self):
39        """Check if something is drawn on screen: i.e. not a black screen.
40
41        @raises TestFail if we cannot determine there was something on screen.
42        """
43
44        def can_take_screenshot():
45            """Check that taking a screenshot can succeed.
46
47            There are cases when trying to take a screenshot on the device
48            fails. e.g. the display has gone to sleep, we have logged out and
49            the UI has not come back up yet etc.
50            """
51            try:
52                graphics_utils.take_screenshot(self.resultsdir,
53                                               'temp screenshot')
54                return True
55            except:
56                return False
57
58        utils.poll_for_condition(
59            can_take_screenshot,
60            sleep_interval=1,
61            desc='Failed to take a screenshot. There may be an issue with this '
62            'ChromeOS image.')
63
64        w, h = graphics_utils.get_internal_resolution()
65        megapixels = (w * h) / 1000000
66        filesize_threshold = 15 * megapixels
67        screenshot1 = graphics_utils.take_screenshot(self.resultsdir,
68                                                     'oobe or signin')
69
70        with chrome.Chrome() as cr:
71            tab = cr.browser.tabs[0]
72            tab.Navigate('chrome://settings')
73            tab.WaitForDocumentReadyStateToBeComplete()
74
75            screenshot2 = graphics_utils.take_screenshot(
76                self.resultsdir, 'settings page')
77
78        for screenshot in [screenshot1, screenshot2]:
79            file_size_kb = os.path.getsize(screenshot) / 1000
80
81            # Use compressed file size to tell if anything is on screen.
82            if file_size_kb > filesize_threshold:
83                return
84
85        raise error.TestFail(
86            'Screenshot filesize is smaller than expected(%s <= %s). This '
87            'indicates that there is nothing on screen. This ChromeOS image '
88            'could be unusable. Check the screenshot in the results folder.' %
89            (file_size_kb, filesize_threshold))
90
91    def test_generated_screenshots_match_expectation(self):
92        """Draws a texture with a soft ellipse twice and captures each image.
93        Compares the output fuzzily against reference images.
94        """
95        self._services = service_stopper.ServiceStopper(['ui'])
96        self._services.stop_services()
97
98        screenshot1_reference = os.path.join(self.bindir,
99                                             'screenshot1_reference.png')
100        screenshot1_generated = os.path.join(self.resultsdir,
101                                             'screenshot1_generated.png')
102        screenshot1_resized = os.path.join(self.resultsdir,
103                                           'screenshot1_generated_resized.png')
104        screenshot2_reference = os.path.join(self.bindir,
105                                             'screenshot2_reference.png')
106        screenshot2_generated = os.path.join(self.resultsdir,
107                                             'screenshot2_generated.png')
108        screenshot2_resized = os.path.join(self.resultsdir,
109                                           'screenshot2_generated_resized.png')
110
111        exefile = os.path.join('/usr/local/', 'glbench', 'bin', 'windowmanagertest');
112
113        # Delay before screenshot: 1 second has caused failures.
114        options = ' --screenshot1_sec 2'
115        options += ' --screenshot2_sec 1'
116        options += ' --cooldown_sec 1'
117        # perceptualdiff can handle only 8 bit images.
118        screenshot_cmd = ' "screenshot %s"'
119        options += ' --screenshot1_cmd' + screenshot_cmd % screenshot1_generated
120        options += ' --screenshot2_cmd' + screenshot_cmd % screenshot2_generated
121
122        cmd = exefile + ' ' + options
123        utils.run(
124            cmd, stdout_tee=utils.TEE_TO_LOGS, stderr_tee=utils.TEE_TO_LOGS)
125
126        convert_cmd = ('convert -channel RGB -colorspace RGB -depth 8'
127                       " -resize '100x100!' %s %s")
128        utils.system(convert_cmd % (screenshot1_generated, screenshot1_resized))
129        utils.system(convert_cmd % (screenshot2_generated, screenshot2_resized))
130        os.remove(screenshot1_generated)
131        os.remove(screenshot2_generated)
132
133        diff_cmd = 'perceptualdiff -verbose %s %s'
134        utils.system(diff_cmd % (screenshot1_reference, screenshot1_resized))
135        utils.system(diff_cmd % (screenshot2_reference, screenshot2_resized))
136
137    def run_once(self):
138        if graphics_utils.get_display_resolution() is None:
139            logging.warning('Skipping test because there is no screen')
140            return
141        self.add_failures('graphics_Sanity')
142        self.wake_screen_with_keyboard()
143        self.test_something_on_screen()
144        self.test_generated_screenshots_match_expectation()
145        self.remove_failures('graphics_Sanity')
146