1# Copyright 2013 The Chromium 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
5"""Runs a Google Maps pixel test.
6Performs several common navigation actions on the map (pan, zoom, rotate) then
7captures a screenshot and compares selected pixels against expected values"""
8
9import json
10import optparse
11import os
12
13import cloud_storage_test_base
14import maps_expectations
15
16from telemetry import benchmark
17from telemetry.core import bitmap
18from telemetry.core import util
19from telemetry.page import page
20from telemetry.page import page_set
21from telemetry.page import page_test
22
23class _MapsValidator(cloud_storage_test_base.ValidatorBase):
24  def CustomizeBrowserOptions(self, options):
25    options.AppendExtraBrowserArgs('--enable-gpu-benchmarking')
26
27  def ValidateAndMeasurePage(self, page, tab, results):
28    # TODO: This should not be necessary, but it's not clear if the test is
29    # failing on the bots in it's absence. Remove once we can verify that it's
30    # safe to do so.
31    _MapsValidator.SpinWaitOnRAF(tab, 3)
32
33    if not tab.screenshot_supported:
34      raise page_test.Failure('Browser does not support screenshot capture')
35    screenshot = tab.Screenshot(5)
36    if not screenshot:
37      raise page_test.Failure('Could not capture screenshot')
38
39    dpr = tab.EvaluateJavaScript('window.devicePixelRatio')
40    expected = self._ReadPixelExpectations(page)
41    self._ValidateScreenshotSamples(
42        page.display_name, screenshot, expected, dpr)
43
44  @staticmethod
45  def SpinWaitOnRAF(tab, iterations, timeout = 60):
46    waitScript = r"""
47      window.__spinWaitOnRAFDone = false;
48      var iterationsLeft = %d;
49
50      function spin() {
51        iterationsLeft--;
52        if (iterationsLeft == 0) {
53          window.__spinWaitOnRAFDone = true;
54          return;
55        }
56        window.requestAnimationFrame(spin);
57      }
58      window.requestAnimationFrame(spin);
59    """ % iterations
60
61    def IsWaitComplete():
62      return tab.EvaluateJavaScript('window.__spinWaitOnRAFDone')
63
64    tab.ExecuteJavaScript(waitScript)
65    util.WaitFor(IsWaitComplete, timeout)
66
67  def _ReadPixelExpectations(self, page):
68    expectations_path = os.path.join(page._base_dir, page.pixel_expectations)
69    with open(expectations_path, 'r') as f:
70      json_contents = json.load(f)
71    return json_contents
72
73
74class MapsPage(page.Page):
75  def __init__(self, page_set, base_dir):
76    super(MapsPage, self).__init__(
77      url='http://localhost:10020/tracker.html',
78      page_set=page_set,
79      base_dir=base_dir,
80      name='Maps.maps_002')
81    self.pixel_expectations = 'data/maps_002_expectations.json'
82
83  def RunNavigateSteps(self, action_runner):
84    action_runner.NavigateToPage(self)
85    action_runner.WaitForJavaScriptCondition(
86        'window.testDone', timeout_in_seconds=180)
87
88
89class Maps(cloud_storage_test_base.TestBase):
90  """Google Maps pixel tests."""
91  test = _MapsValidator
92
93  def CreateExpectations(self, page_set):
94    return maps_expectations.MapsExpectations()
95
96  def CreatePageSet(self, options):
97    page_set_path = os.path.join(
98        util.GetChromiumSrcDir(), 'content', 'test', 'gpu', 'page_sets')
99    ps = page_set.PageSet(archive_data_file='data/maps.json',
100                          make_javascript_deterministic=False,
101                          file_path=page_set_path,
102                          bucket=page_set.PUBLIC_BUCKET)
103    ps.AddPage(MapsPage(ps, ps.base_dir))
104    return ps
105