| OLD | NEW |
| (Empty) |
| 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. | |
| 6 Performs several common navigation actions on the map (pan, zoom, rotate) then | |
| 7 captures a screenshot and compares selected pixels against expected values""" | |
| 8 | |
| 9 import json | |
| 10 import os | |
| 11 | |
| 12 from gpu_tests import cloud_storage_test_base | |
| 13 from gpu_tests import gpu_test_base | |
| 14 from gpu_tests import maps_expectations | |
| 15 from gpu_tests import path_util | |
| 16 | |
| 17 from telemetry.core import util | |
| 18 from telemetry.page import legacy_page_test | |
| 19 from telemetry import story as story_module | |
| 20 from telemetry.story import story_set as story_set_module | |
| 21 | |
| 22 | |
| 23 class MapsValidator(cloud_storage_test_base.ValidatorBase): | |
| 24 def __init__(self): | |
| 25 super(MapsValidator, self).__init__() | |
| 26 | |
| 27 def CustomizeBrowserOptions(self, options): | |
| 28 # --test-type=gpu is used only to suppress the "Google API Keys are missing" | |
| 29 # infobar, which causes flakiness in tests. | |
| 30 options.AppendExtraBrowserArgs(['--enable-gpu-benchmarking', | |
| 31 '--test-type=gpu']) | |
| 32 | |
| 33 def ValidateAndMeasurePage(self, page, tab, results): | |
| 34 # TODO: This should not be necessary, but it's not clear if the test is | |
| 35 # failing on the bots in it's absence. Remove once we can verify that it's | |
| 36 # safe to do so. | |
| 37 MapsValidator.SpinWaitOnRAF(tab, 3) | |
| 38 | |
| 39 if not tab.screenshot_supported: | |
| 40 raise legacy_page_test.Failure( | |
| 41 'Browser does not support screenshot capture') | |
| 42 screenshot = tab.Screenshot(5) | |
| 43 if screenshot is None: | |
| 44 raise legacy_page_test.Failure('Could not capture screenshot') | |
| 45 | |
| 46 dpr = tab.EvaluateJavaScript('window.devicePixelRatio') | |
| 47 print 'Maps\' devicePixelRatio is ' + str(dpr) | |
| 48 # Even though the Maps test uses a fixed devicePixelRatio so that | |
| 49 # it fetches all of the map tiles at the same resolution, on two | |
| 50 # different devices with the same devicePixelRatio (a Retina | |
| 51 # MacBook Pro and a Nexus 9), different scale factors of the final | |
| 52 # screenshot are observed. Hack around this by specifying a scale | |
| 53 # factor for these bots in the test expectations. This relies on | |
| 54 # the test-machine-name argument being specified on the command | |
| 55 # line. | |
| 56 expected = self._ReadPixelExpectations(page) | |
| 57 self._ValidateScreenshotSamples( | |
| 58 tab, page.display_name, screenshot, expected, dpr) | |
| 59 | |
| 60 @staticmethod | |
| 61 def SpinWaitOnRAF(tab, iterations, timeout=60): | |
| 62 waitScript = r""" | |
| 63 window.__spinWaitOnRAFDone = false; | |
| 64 var iterationsLeft = %d; | |
| 65 | |
| 66 function spin() { | |
| 67 iterationsLeft--; | |
| 68 if (iterationsLeft == 0) { | |
| 69 window.__spinWaitOnRAFDone = true; | |
| 70 return; | |
| 71 } | |
| 72 window.requestAnimationFrame(spin); | |
| 73 } | |
| 74 window.requestAnimationFrame(spin); | |
| 75 """ % iterations | |
| 76 | |
| 77 def IsWaitComplete(): | |
| 78 return tab.EvaluateJavaScript('window.__spinWaitOnRAFDone') | |
| 79 | |
| 80 tab.ExecuteJavaScript(waitScript) | |
| 81 util.WaitFor(IsWaitComplete, timeout) | |
| 82 | |
| 83 def _ReadPixelExpectations(self, page): | |
| 84 expectations_path = os.path.join(page._base_dir, page.pixel_expectations) | |
| 85 with open(expectations_path, 'r') as f: | |
| 86 json_contents = json.load(f) | |
| 87 return json_contents | |
| 88 | |
| 89 | |
| 90 class MapsPage(gpu_test_base.PageBase): | |
| 91 def __init__(self, story_set, base_dir, expectations): | |
| 92 super(MapsPage, self).__init__( | |
| 93 url='http://map-test/performance.html', | |
| 94 page_set=story_set, | |
| 95 base_dir=base_dir, | |
| 96 name='Maps.maps_004', | |
| 97 make_javascript_deterministic=False, | |
| 98 expectations=expectations) | |
| 99 self.pixel_expectations = 'data/maps_004_expectations.json' | |
| 100 | |
| 101 def RunNavigateSteps(self, action_runner): | |
| 102 super(MapsPage, self).RunNavigateSteps(action_runner) | |
| 103 action_runner.WaitForJavaScriptCondition( | |
| 104 'window.testDone', timeout_in_seconds=180) | |
| 105 | |
| 106 | |
| 107 class Maps(cloud_storage_test_base.CloudStorageTestBase): | |
| 108 """Google Maps pixel tests. | |
| 109 | |
| 110 Note: the WPR for this test was recorded from the smoothness.maps | |
| 111 benchmark's similar page. The Maps team gave us a build of their | |
| 112 test. The only modification to the test was to config.js, where the | |
| 113 width and height query args were set to 800 by 600. The WPR was | |
| 114 recorded with: | |
| 115 | |
| 116 tools/perf/record_wpr smoothness_maps --browser=system | |
| 117 | |
| 118 This would produce maps_???.wpr and maps.json were copied from | |
| 119 tools/perf/page_sets/data into content/test/gpu/page_sets/data. | |
| 120 It worths noting that telemetry no longer allows replaying URL that has form | |
| 121 of local host. If the recording was created for locahost URL, ones can update | |
| 122 the host name by running: | |
| 123 web-page-replay/httparchive.py remap-host maps_004.wpr \ | |
| 124 localhost:10020 map-test | |
| 125 (web-page-replay/ can be found in third_party/catapult/telemetry/third_party/) | |
| 126 After update the host name in WPR archive, please remember to update the host | |
| 127 URL in content/test/gpu/gpu_tests/maps.py as well. | |
| 128 | |
| 129 To upload the maps_???.wpr to cloud storage, one would run: | |
| 130 depot_tools/upload_to_google_storage.py --bucket=chromium-telemetry \ | |
| 131 maps_???.wpr | |
| 132 The same sha1 file and json file need to be copied into both of these | |
| 133 directories in any CL which updates the recording.""" | |
| 134 test = MapsValidator | |
| 135 | |
| 136 @classmethod | |
| 137 def Name(cls): | |
| 138 return 'maps' | |
| 139 | |
| 140 def _CreateExpectations(self): | |
| 141 return maps_expectations.MapsExpectations() | |
| 142 | |
| 143 def CreateStorySet(self, options): | |
| 144 story_set_path = os.path.join( | |
| 145 path_util.GetChromiumSrcDir(), 'content', 'test', 'gpu', 'page_sets') | |
| 146 ps = story_set_module.StorySet( | |
| 147 archive_data_file='data/maps.json', | |
| 148 base_dir=story_set_path, | |
| 149 cloud_storage_bucket=story_module.PUBLIC_BUCKET) | |
| 150 ps.AddStory(MapsPage(ps, ps.base_dir, self.GetExpectations())) | |
| 151 return ps | |
| OLD | NEW |