1# Copyright (c) 2014 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"""This is a client side WebGL performance test.
5
6http://hg.mozilla.org/users/bjacob_mozilla.com/webgl-perf-tests/raw-file/3729e8afac99/index.html
7
8From the sources:
9Keep in mind that these tests are not realistic workloads. These are not
10benchmarks aiming to compare browser or GPU performance. These are only useful
11to catch performance regressions in a given browser and system.
12"""
13
14import logging
15import os
16
17from autotest_lib.client.bin import test
18from autotest_lib.client.bin import utils
19from autotest_lib.client.common_lib import error
20from autotest_lib.client.common_lib.cros import chrome
21from autotest_lib.client.cros.graphics import graphics_utils
22
23
24class graphics_WebGLPerformance(test.test):
25    """WebGL performance graphics test."""
26    version = 1
27    GSC = None
28    _test_duration_secs = 0
29    perf_keyval = {}
30
31    def setup(self):
32        self.job.setup_dep(['webgl_perf'])
33        self.job.setup_dep(['graphics'])
34
35    def initialize(self):
36        self.GSC = graphics_utils.GraphicsStateChecker()
37
38    def cleanup(self):
39        if self.GSC:
40            keyvals = self.GSC.get_memory_keyvals()
41            for key, val in keyvals.iteritems():
42                self.output_perf_value(
43                    description=key,
44                    value=val,
45                    units='bytes',
46                    higher_is_better=False)
47            self.GSC.finalize()
48            self.write_perf_keyval(keyvals)
49
50    def run_performance_test(self, browser, test_url):
51        """Runs the performance test from the given url.
52
53        @param browser: The Browser object to run the test with.
54        @param test_url: The URL to the performance test site.
55        """
56        if not utils.wait_for_idle_cpu(60.0, 0.1):
57            if not utils.wait_for_idle_cpu(20.0, 0.2):
58                raise error.TestFail('Failed: Could not get idle CPU.')
59
60        # Kick off test.
61        tab = browser.tabs.New()
62        tab.Navigate(test_url)
63        tab.Activate()
64        tab.WaitForDocumentReadyStateToBeComplete()
65
66        # Wait for test completion.
67        tab.WaitForJavaScriptCondition('time_ms_geom_mean > 0.0',
68                                       timeout=self._test_duration_secs)
69
70        # Get the geometric mean of individual runtimes.
71        time_ms_geom_mean = tab.EvaluateJavaScript('time_ms_geom_mean')
72        logging.info('WebGLPerformance: time_ms_geom_mean = %f',
73                     time_ms_geom_mean)
74
75        # Output numbers for plotting by harness.
76        keyvals = {}
77        keyvals['time_ms_geom_mean'] = time_ms_geom_mean
78        self.write_perf_keyval(keyvals)
79        self.output_perf_value(
80            description='time_geom_mean',
81            value=time_ms_geom_mean,
82            units='ms',
83            higher_is_better=False,
84            graph='time_geom_mean')
85        # Add extra value to the graph distinguishing different boards.
86        variant = utils.get_board_with_frequency_and_memory()
87        desc = 'time_geom_mean-%s' % variant
88        self.output_perf_value(
89            description=desc,
90            value=time_ms_geom_mean,
91            units='ms',
92            higher_is_better=False,
93            graph='time_geom_mean')
94
95        # Get a copy of the test report.
96        test_report = tab.EvaluateJavaScript('test_report')
97        results_path = os.path.join(
98            self.bindir,
99            '../../results/default/graphics_WebGLPerformance/test_report.html')
100        f = open(results_path, 'w+')
101        f.write(test_report)
102        f.close()
103
104        tab.Close()
105
106    def run_once(self, test_duration_secs=2700, fullscreen=True):
107        """Finds a brower with telemetry, and run the test.
108
109        @param test_duration_secs: The test duration in seconds.
110        @param fullscreen: Whether to run the test in fullscreen.
111        """
112        # To avoid 0ms on fast machines like samus the workload was increased.
113        # Unfortunately that makes running on slow machines impractical without
114        # deviating from upstream too much.
115        if utils.get_gpu_family() == 'pinetrail':
116            # TODO(ihf): return a TestPass(message) once available.
117            logging.warning('Test is too slow to run regularly.')
118            return
119
120        self._test_duration_secs = test_duration_secs
121        ext_paths = []
122        if fullscreen:
123            ext_paths.append(
124                os.path.join(self.autodir, 'deps', 'graphics',
125                             'graphics_test_extension'))
126
127        with chrome.Chrome(logged_in=False,
128                           extension_paths=ext_paths,
129                           init_network_controller=True) as cr:
130            websrc_dir = os.path.join(self.autodir, 'deps', 'webgl_perf', 'src')
131            if not cr.browser.platform.SetHTTPServerDirectories(websrc_dir):
132                raise error.TestFail('Failed: Unable to start HTTP server')
133            test_url = cr.browser.platform.http_server.UrlOf(
134                os.path.join(websrc_dir, 'index.html'))
135            self.run_performance_test(cr.browser, test_url)
136