Chromium Code Reviews| Index: tools/perf/page_sets/infinite_scroll_cases.py |
| diff --git a/tools/perf/page_sets/infinite_scroll_cases.py b/tools/perf/page_sets/infinite_scroll_cases.py |
| index 7930a6e70a2cc9078b1f9fa0ba57692faf46991e..25221f0850cf82d3004812ab3df5d04d0571a000 100644 |
| --- a/tools/perf/page_sets/infinite_scroll_cases.py |
| +++ b/tools/perf/page_sets/infinite_scroll_cases.py |
| @@ -1,80 +1,157 @@ |
| -# Copyright 2015 The Chromium Authors. All rights reserved. |
| +# Copyright 2017 The Chromium Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| -from telemetry.page import page as page_module |
| + |
| +import sys |
| + |
| +from page_sets.login_helpers import facebook_login |
| +from page_sets.system_health import platforms |
| +from telemetry.core import discover |
| +from telemetry.page import page |
| from telemetry.page import shared_page_state |
| from telemetry import story |
| -TIME_TO_WAIT_BEFORE_STARTING_IN_SECONDS = 5 |
| -SCROLL_TIMEOUT_IN_SECONDS = 120 |
| +class _InfiniteScrollStory(page.Page): |
| + """ Base class for infinite scroll stories.""" |
| -# TODO(ulan): Remove this once crbug.com/541508 is fixed. |
| -STARTUP_SCRIPT = ''' |
| - window.WebSocket = undefined; |
| - window.Worker = undefined; |
| - window.performance = undefined;''' |
| + NAME = NotImplemented |
| + URL = NotImplemented |
| + SUPPORTED_PLATFORMS = platforms.ALL_PLATFORMS |
| + SCROLL_DISTANCE = 25000 |
| + SCROLL_STEP = 1000 |
| + MAX_SCROLL_RETRIES = 3 |
| + TIME_BEFORE_SCROLL_RETRY_IN_SECONDS = 1 |
| + TIME_TO_WAIT_BEFORE_STARTING_IN_SECONDS = 5 |
| -class InfiniteScrollPage(page_module.Page): |
| - def __init__(self, url, page_set, name, scroll_amount, delay, repeat, |
| - credentials=None): |
| - super(InfiniteScrollPage, self).__init__( |
| - url=url, page_set=page_set, name=name, |
| + def __init__(self, story_set): |
| + super(_InfiniteScrollStory, self).__init__( |
| + page_set=story_set, url=self.URL, name=self.NAME, |
| shared_page_state_class=shared_page_state.SharedPageState, |
| - credentials_path='data/credentials.json') |
| - self.credentials = credentials |
| - self.script_to_evaluate_on_commit = STARTUP_SCRIPT |
| - self.scroll_amount = scroll_amount |
| - self.delay = delay |
| - self.repeat = repeat |
| + credentials_path='data/credentials.json') |
| + # TODO(ulan): Remove this once crbug.com/541508 is fixed. |
| + self.script_to_evaluate_on_commit = ''' |
| + window.WebSocket = undefined; |
| + window.Worker = undefined; |
| + window.performance = undefined;''' |
|
nednguyen
2017/03/30 13:09:46
Does this make any of the page's JS fail? Seems a
ulan
2017/03/30 14:35:09
This part did not change with this CL. At the time
|
| def RunPageInteractions(self, action_runner): |
| - self._WaitAction(action_runner) |
| - self._ScrollAction(action_runner, self.scroll_amount, self.delay, |
| - self.repeat) |
| - |
| - def _ScrollAction(self, action_runner, scroll_amount, delay, repeat): |
| - with action_runner.CreateInteraction('Begin'): |
| - action_runner.tab.browser.DumpMemory() |
| - with action_runner.CreateInteraction('Scrolling'): |
| - action_runner.RepeatableBrowserDrivenScroll( |
| - y_scroll_distance_ratio=scroll_amount, |
| - repeat_delay_ms=delay, |
| - repeat_count=repeat, |
| - timeout=SCROLL_TIMEOUT_IN_SECONDS) |
| - with action_runner.CreateInteraction('End'): |
| - action_runner.tab.browser.DumpMemory() |
| - |
| - def _WaitAction(self, action_runner): |
| with action_runner.CreateInteraction('Load'): |
| action_runner.WaitForJavaScriptCondition( |
| 'document.body != null && ' |
| 'document.body.scrollHeight > window.innerHeight && ' |
| '!document.body.addEventListener("touchstart", function() {})') |
| with action_runner.CreateInteraction('Wait'): |
| - action_runner.Wait(TIME_TO_WAIT_BEFORE_STARTING_IN_SECONDS) |
| + action_runner.Wait(self.TIME_TO_WAIT_BEFORE_STARTING_IN_SECONDS) |
| with action_runner.CreateInteraction('GC'): |
| action_runner.ForceGarbageCollection() |
| + with action_runner.CreateInteraction('Begin'): |
|
nednguyen
2017/03/30 13:09:46
not in this CL but these interactions are only nee
ulan
2017/03/30 14:35:08
Yep, will do in separete CL.
|
| + action_runner.tab.browser.DumpMemory() |
| + with action_runner.CreateInteraction('Scrolling'): |
| + self._Scroll(action_runner, self.SCROLL_DISTANCE, self.SCROLL_STEP) |
| + with action_runner.CreateInteraction('End'): |
| + action_runner.tab.browser.DumpMemory() |
| + def _Scroll(self, action_runner, distance, step_size): |
|
nednguyen
2017/03/30 13:09:46
this method seems useful & common enough to be an
ulan
2017/03/30 14:35:09
OK. I would wait until it is needed by another pag
|
| + """ This function scrolls the webpage by the given scroll distance in |
| + multiple steps, where each step (except the last one) has the given size. |
| -class InfiniteScrollPageSet(story.StorySet): |
| - """ Top pages that can be scrolled for many pages. """ |
| + If scrolling gets stuck, the functions retries scrolling MAX_SCROLL_RETRIES |
| + times waiting TIME_BEFORE_SCROLL_RETRY_IN_SECONDS seconds between retries. |
| + """ |
| + remaining = distance - action_runner.EvaluateJavaScript('window.scrollY') |
| + retry_count = 0 |
| + # Scroll until the window.scrollY is within 1 pixel of the target distance. |
| + while remaining > 1: |
| + action_runner.ScrollPage(distance=min(remaining, step_size) + 1) |
| + new_remaining = (distance - |
| + action_runner.EvaluateJavaScript('window.scrollY')) |
| + if remaining == new_remaining: |
| + # Scrolling is stuck. This can happen if the page is loading |
| + # resources. Give the page some time and retry scrolling. |
| + if retry_count == self.MAX_SCROLL_RETRIES: |
| + raise Exception('Scrolling stuck at %d' % remaining) |
| + retry_count += 1 |
| + action_runner.Wait(self.TIME_BEFORE_SCROLL_RETRY_IN_SECONDS) |
| + else: |
| + retry_count = 0 |
| + remaining = new_remaining |
| + |
| +class DiscourseDesktopStory(_InfiniteScrollStory): |
| + NAME = 'discourse' |
| + URL = ('https://meta.discourse.org/t/the-official-discourse-tags-plugin' + |
| + '-discourse-tagging/26482') |
| + SUPPORTED_PLATFORMS = platforms.DESKTOP_ONLY |
| + |
| +class DiscourseMobileStory(_InfiniteScrollStory): |
| + NAME = 'discourse' |
| + URL = ('https://meta.discourse.org/t/the-official-discourse-tags-plugin' + |
| + '-discourse-tagging/26482') |
| + SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY |
| + SCROLL_DISTANCE = 15000 |
| + |
| +class FacebookDesktopStory(_InfiniteScrollStory): |
| + NAME = 'facebook' |
| + URL = 'https://www.facebook.com/shakira' |
| + SUPPORTED_PLATFORMS = platforms.DESKTOP_ONLY |
| + |
| +class FacebookMobileStory(_InfiniteScrollStory): |
| + NAME = 'facebook' |
| + URL = 'https://m.facebook.com/shakira' |
| + SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY |
| + def RunNavigateSteps(self, action_runner): |
| + facebook_login.LoginWithMobileSite( |
| + action_runner, 'facebook3', self.credentials_path) |
| + super(FacebookMobileStory, self).RunNavigateSteps(action_runner) |
| + |
| +class FlickrDesktopStory(_InfiniteScrollStory): |
| + NAME = 'flickr' |
| + URL = 'https://www.flickr.com/explore' |
| + SUPPORTED_PLATFORMS = platforms.DESKTOP_ONLY |
| + |
| +class FlickrMobileStory(_InfiniteScrollStory): |
| + NAME = 'flickr' |
| + URL = 'https://www.flickr.com/explore' |
| + SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY |
| + SCROLL_DISTANCE = 10000 |
| + |
| +class PinterestMobileStory(_InfiniteScrollStory): |
| + NAME = 'pinterest' |
| + URL = 'https://www.pinterest.com/all' |
| + SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY |
| + |
| +class TumblrStory(_InfiniteScrollStory): |
| + NAME = 'tumblr' |
| + URL = 'http://techcrunch.tumblr.com/' |
| + |
| +class TwitterDesktopStory(_InfiniteScrollStory): |
| + NAME = 'twitter' |
| + URL = 'https://twitter.com/taylorswift13' |
| + SUPPORTED_PLATFORMS = platforms.DESKTOP_ONLY |
| + |
| +class InfiniteScrollStorySet(story.StorySet): |
| + """ Desktop story set. """ |
| def __init__(self): |
| - super(InfiniteScrollPageSet, self).__init__( |
| + super(InfiniteScrollStorySet, self).__init__( |
| archive_data_file='data/infinite_scroll.json', |
| cloud_storage_bucket=story.PARTNER_BUCKET) |
| - # The scroll distance is chosen such that the page can be scrolled |
| - # continuously through the test without hitting the end of the page. |
| - SCROLL_FAR = 60 |
| - SCROLL_PAGE = 1 |
| - pages = [ |
| - ('https://www.facebook.com/shakira', 'facebook', SCROLL_FAR, 0, 0), |
| - ('https://twitter.com/taylorswift13', 'twitter', SCROLL_PAGE, 10, 30), |
| - ('http://techcrunch.tumblr.com/', 'tumblr', SCROLL_FAR, 0, 0), |
| - ('https://www.flickr.com/explore', 'flickr', SCROLL_FAR, 0, 0), |
| - ('https://meta.discourse.org/t/the-official-discourse-tags-plugin-discourse-tagging/26482', |
| - 'discourse', SCROLL_PAGE, 10, 30) |
| - ] |
| - for (url, name, scroll_amount, delay, repeat) in pages: |
| - self.AddStory( |
| - InfiniteScrollPage(url, self, name, scroll_amount, delay, repeat)) |
| + for story_class in _FindInfiniteScrollStoryClasses(platforms.DESKTOP): |
| + self.AddStory(story_class(self)) |
| + |
| +class MobileInfiniteScrollStorySet(story.StorySet): |
| + """ Mobile story set. """ |
| + def __init__(self): |
| + super(MobileInfiniteScrollStorySet, self).__init__( |
| + archive_data_file='data/mobile_infinite_scroll.json', |
| + cloud_storage_bucket=story.PARTNER_BUCKET) |
| + for story_class in _FindInfiniteScrollStoryClasses(platforms.MOBILE): |
| + self.AddStory(story_class(self)) |
| + |
| +def _FindInfiniteScrollStoryClasses(platform): |
| + # Sort the classes by their names so that their order is stable and |
| + # deterministic. |
| + for unused_cls_name, cls in sorted(discover.DiscoverClassesInModule( |
| + module=sys.modules[__name__], base_class=_InfiniteScrollStory, |
| + index_by_class_name=True).iteritems()): |
| + if platform in cls.SUPPORTED_PLATFORMS: |
| + yield cls |