• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2013 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 many planets deep test."""
5
6import numpy
7import os
8import time
9
10from autotest_lib.client.bin import test
11from autotest_lib.client.common_lib import error
12from autotest_lib.client.bin import utils
13from autotest_lib.client.common_lib.cros import chrome
14from autotest_lib.client.cros.graphics import graphics_utils
15
16
17class graphics_WebGLManyPlanetsDeep(test.test):
18    """WebGL many planets deep graphics test."""
19    version = 1
20    GSC = None
21    frame_data = {}
22    perf_keyval = {}
23    test_duration_secs = 30
24
25    def setup(self):
26        self.job.setup_dep(['webgl_mpd'])
27        self.job.setup_dep(['graphics'])
28
29    def initialize(self):
30        self.GSC = graphics_utils.GraphicsStateChecker()
31
32    def cleanup(self):
33        if self.GSC:
34            keyvals = self.GSC.get_memory_keyvals()
35            for key, val in keyvals.iteritems():
36                self.output_perf_value(
37                    description=key,
38                    value=val,
39                    units='bytes',
40                    higher_is_better=False)
41            self.GSC.finalize()
42            self.write_perf_keyval(keyvals)
43
44    def run_many_planets_deep_test(self, browser, test_url):
45        """Runs the many planets deep test from the given url.
46
47        @param browser: The Browser object to run the test with.
48        @param test_url: The URL to the many planets deep test site.
49        """
50        if not utils.wait_for_idle_cpu(60.0, 0.1):
51            if not utils.wait_for_idle_cpu(20.0, 0.2):
52                raise error.TestFail('Failed: Could not get idle CPU.')
53
54        tab = browser.tabs.New()
55        tab.Navigate(test_url)
56        tab.Activate()
57        tab.WaitForDocumentReadyStateToBeComplete()
58
59        # Wait 3 seconds for the page to stabilize.
60        time.sleep(3)
61
62        # Reset our own FPS counter and start recording FPS and rendering time.
63        end_time = time.time() + self.test_duration_secs
64        tab.ExecuteJavaScript('g_crosFpsCounter.reset();')
65        while time.time() < end_time:
66            frame_data = tab.EvaluateJavaScript(
67                'g_crosFpsCounter.getFrameData();')
68            for datum in frame_data:
69                if not datum or datum['seq'] in self.frame_data:
70                    continue
71                self.frame_data[datum['seq']] = {
72                    'start_time': datum['startTime'],
73                    'frame_elapsed_time': datum['frameElapsedTime'],
74                    'js_elapsed_time': datum['jsElapsedTime']
75                }
76            time.sleep(1)
77        tab.Close()
78
79    def calculate_perf_values(self):
80        """Calculates all the perf values from the collected data."""
81        arr = numpy.array([[v['frame_elapsed_time'], v['js_elapsed_time']]
82                           for v in self.frame_data.itervalues()])
83        std = arr.std(axis=0)
84        mean = arr.mean(axis=0)
85        avg_fps = 1000.0 / mean[0]
86        self.perf_keyval.update({
87            'average_fps': avg_fps,
88            'per_frame_dt_ms_std': std[0],
89            'per_frame_dt_ms_mean': mean[0],
90            'js_render_time_ms_std': std[1],
91            'js_render_time_ms_mean': mean[1]
92        })
93        self.output_perf_value(
94            description='average_fps',
95            value=avg_fps,
96            units='fps',
97            higher_is_better=True)
98
99        with open('frame_data', 'w') as f:
100            line_format = '%10s %20s %20s %20s\n'
101            f.write(line_format % ('seq', 'start_time', 'frame_render_time_ms',
102                                   'js_render_time_ms'))
103            for k in sorted(self.frame_data.keys()):
104                d = self.frame_data[k]
105                f.write(line_format % (k, d['start_time'],
106                                       d['frame_elapsed_time'],
107                                       d['js_elapsed_time']))
108
109    def run_once(self, test_duration_secs=30, fullscreen=True):
110        """Finds a brower with telemetry, and run the test.
111
112        @param test_duration_secs: The test duration in seconds to run the test
113                for.
114        @param fullscreen: Whether to run the test in fullscreen.
115        """
116        self.test_duration_secs = test_duration_secs
117
118        ext_paths = []
119        if fullscreen:
120            ext_paths.append(
121                os.path.join(self.autodir, 'deps', 'graphics',
122                             'graphics_test_extension'))
123
124        with chrome.Chrome(logged_in=False,
125                           extension_paths=ext_paths,
126                           init_network_controller=True) as cr:
127            websrc_dir = os.path.join(self.autodir, 'deps', 'webgl_mpd', 'src')
128            if not cr.browser.platform.SetHTTPServerDirectories(websrc_dir):
129                raise error.TestFail('Failed: Unable to start HTTP server')
130            test_url = cr.browser.platform.http_server.UrlOf(
131                os.path.join(websrc_dir, 'ManyPlanetsDeep.html'))
132            self.run_many_planets_deep_test(cr.browser, test_url)
133
134        self.calculate_perf_values()
135        self.write_perf_keyval(self.perf_keyval)
136