blob: 62b6a6c3f44409c9f6af8d980ead54ccf230e649 [file] [log] [blame]
# Copyright 2016 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 page_sets.system_health import platforms
from page_sets.system_health import story_tags
from telemetry import decorators
from telemetry.page import page
from telemetry.page import shared_page_state
# Extra wait time after the page has loaded required by the loading metric. We
# use it in all benchmarks to avoid divergence between benchmarks.
# TODO(petrcermak): Switch the memory benchmarks to use it as well.
_WAIT_TIME_AFTER_LOAD = 10
class _SystemHealthSharedState(shared_page_state.SharedPageState):
"""Shared state which enables disabling stories on individual platforms.
This class adds support for enabling/disabling individual stories on
individual platforms using the same approaches as for benchmarks:
1. Disabled/Enabled decorator:
@decorators.Disabled('win')
class Story(system_health_story.SystemHealthStory):
...
2. ShouldDisable method:
class Story(system_health_story.SystemHealthStory):
...
@classmethod
def ShouldDisable(cls, possible_browser):
return possible_browser.platform.GetOSName() == 'win'
"""
def CanRunStory(self, story):
if self._finder_options.run_disabled_tests:
return True
return story.CanRun(self.possible_browser)
class _MetaSystemHealthStory(type):
"""Metaclass for SystemHealthStory."""
@property
def ABSTRACT_STORY(cls):
"""Class field marking whether the class is abstract.
If true, the story will NOT be instantiated and added to a System Health
story set. This field is NOT inherited by subclasses (that's why it's
defined on the metaclass).
"""
return cls.__dict__.get('ABSTRACT_STORY', False)
class SystemHealthStory(page.Page):
"""Abstract base class for System Health user stories."""
__metaclass__ = _MetaSystemHealthStory
# The full name of a single page story has the form CASE:GROUP:PAGE (e.g.
# 'load:search:google').
NAME = NotImplemented
URL = NotImplemented
ABSTRACT_STORY = True
SUPPORTED_PLATFORMS = platforms.ALL_PLATFORMS
TAGS = None
PLATFORM_SPECIFIC = False
def __init__(self, story_set, take_memory_measurement):
case, group, _ = self.NAME.split(':')
tags = []
if self.TAGS:
for t in self.TAGS:
assert t in story_tags.ALL_TAGS
tags.append(t.name)
super(SystemHealthStory, self).__init__(
shared_page_state_class=_SystemHealthSharedState, page_set=story_set,
name=self.NAME, url=self.URL, tags=tags,
credentials_path='../data/credentials.json',
grouping_keys={'case': case, 'group': group},
platform_specific=self.PLATFORM_SPECIFIC)
self._take_memory_measurement = take_memory_measurement
@classmethod
def GetStoryDescription(cls):
if cls.__doc__:
return cls.__doc__
return cls.GenerateStoryDescription()
@classmethod
def GenerateStoryDescription(cls):
""" Subclasses of SystemHealthStory can override this to auto generate
their story description.
However, it's recommended to use the Python docstring to describe the user
stories instead and this should only be used for very repetitive cases.
"""
return None
@classmethod
def CanRun(cls, possible_browser):
if (decorators.ShouldSkip(cls, possible_browser)[0] or
cls.ShouldDisable(possible_browser)):
return False
return True
@classmethod
def ShouldDisable(cls, possible_browser):
"""Override this method to disable a story under specific conditions.
This method is modelled after telemetry.benchmark.Benchmark.ShouldDisable().
"""
del possible_browser
return False
def _Measure(self, action_runner):
if self._take_memory_measurement:
action_runner.MeasureMemory(deterministic_mode=True)
else:
action_runner.Wait(_WAIT_TIME_AFTER_LOAD)
def _Login(self, action_runner):
pass
def _DidLoadDocument(self, action_runner):
pass
def RunNavigateSteps(self, action_runner):
self._Login(action_runner)
super(SystemHealthStory, self).RunNavigateSteps(action_runner)
def RunPageInteractions(self, action_runner):
action_runner.tab.WaitForDocumentReadyStateToBeComplete()
self._DidLoadDocument(action_runner)
self._Measure(action_runner)