Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(478)

Unified Diff: telemetry/telemetry/story/expectations.py

Issue 2843403005: [Telemetry] Add Expectation module that enables disabling benchmarks/stories (Closed)
Patch Set: 30 -> 50 Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: telemetry/telemetry/story/expectations.py
diff --git a/telemetry/telemetry/story/expectations.py b/telemetry/telemetry/story/expectations.py
new file mode 100644
index 0000000000000000000000000000000000000000..1d5292718b64be49c27488e87cf9ad0d90acc435
--- /dev/null
+++ b/telemetry/telemetry/story/expectations.py
@@ -0,0 +1,165 @@
+# 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.
+
+import logging
+
+
+class StoryExpectations(object):
+ """An object that contains disabling expectations for benchmarks and stories.
+
+ Example Usage:
+ class FooBenchmarkExpectations(expectations.StoryExpectations):
+ def SetExpectations(self):
+ self.DisableBenchmark([expectations.ALL_WIN], 'crbug.com/123')
+ self.DisableBenchmark([expectations.ALL_MOBILE], 'Desktop Benchmark')
+ self.DisableStory('story_name1', [expectations.ALL_MAC], 'crbug.com/456')
+ self.DisableStory('story_name2', [expectations.ALL], 'crbug.com/789')
+ ...
+ """
+ def __init__(self):
+ self._disabled_platforms = []
+ self._expectations = {}
+ self._frozen = False
+ self.SetExpectations()
+ self._Freeze()
+
+ def SetExpectations(self):
+ """Sets the Expectations for test disabling
+
+ Override in subclasses to disable tests."""
+ pass
+
+ def _Freeze(self):
+ self._frozen = True
+
+ def DisableBenchmark(self, conditions, reason):
+ """Disable benchmark under conditions pased to method.
charliea (OOO until 10-5) 2017/05/15 21:15:41 s/pased/passed
charliea (OOO until 10-5) 2017/05/15 21:15:42 supernit suggestion: use "given" instead of "passe
rnephew (Reviews Here) 2017/05/15 21:36:06 Done.
rnephew (Reviews Here) 2017/05/15 21:36:06 Done.
+
+ Example:
+ DisableBenchmark([expectations.ALL_MOBILE], 'Desktop benchmark')
+ DisableBenchmark([expectations.ALL_WIN], 'crbug.com/123')
+
+ Args:
+ conditions: List of _TestCondition subclasses.
+ reason: Reason for disabling the benchmark.
+ """
+ assert reason, 'A reason for disabling must be given.'
+ assert not self._frozen, ('Cannot disable benchmark on a frozen '
+ 'StoryExpectation object.')
+ for condition in conditions:
+ assert isinstance(condition, _TestCondition)
+
+ self._disabled_platforms.append((conditions, reason))
+
+ def IsBenchmarkDisabled(self, platform):
+ """Returns if the benchmark has been disabled for the platform.
charliea (OOO until 10-5) 2017/05/15 21:15:41 I think that you can collapse this whole thing dow
rnephew (Reviews Here) 2017/05/15 21:36:06 Done.
+
+ Args:
+ platform: A platform object.
+
+ Returns:
+ Reason if disabled, None otherwise.
+ """
+ for conditions, reason in self._disabled_platforms:
+ for condition in conditions:
+ if condition.ShouldDisable(platform):
+ logging.info('Benchmark disabled on %s due to %s.',
+ condition, reason)
+ return reason
+ return None
+
+ def DisableStory(self, story_name, conditions, reason):
+ """Disable story under given conditions.
charliea (OOO until 10-5) 2017/05/15 21:15:41 supernit: s/Disables story under given conditions.
rnephew (Reviews Here) 2017/05/15 21:36:06 Done.
+
+ Example:
+ DisableStory('story_name', [expectations.ALL_WIN], 'crbug.com/123')
+
+ Args:
+ story_name: Name of the story to disable passed as a string.
+ conditions: List of _TestCondition subclasses.
+ reason: Reason for disabling the story.
+ """
+ assert reason, 'A reason for disabling must be given.'
+ assert len(story_name) < 50, (
+ "Story name exceeds limit of 50 characters. This limit is in place to "
+ "encourage Telemetry benchmark owners to use short, simple story names "
+ "(e.g. 'google_search_images', not "
+ "'http://www.google.com/images/1234/abc')."
+
+ )
+ assert not self._frozen, ('Cannot disable stories on a frozen '
+ 'StoryExpectation object.')
+ for condition in conditions:
+ assert isinstance(condition, _TestCondition)
+ if not self._expectations.get(story_name):
+ self._expectations[story_name] = []
+ self._expectations[story_name].append((conditions, reason))
+
+ def IsStoryDisabled(self, story, platform):
+ """Returns if the story has been disabled for the current platform.
charliea (OOO until 10-5) 2017/05/15 21:15:42 See notes for IsBenchmarkDisabled
rnephew (Reviews Here) 2017/05/15 21:36:06 Done.
+
+ Args:
+ story: Story object that contains a display_name property.
+ platform: A platform object.
+
+ Returns:
+ Reason if disabled, None otherwise.
+ """
+
charliea (OOO until 10-5) 2017/05/15 21:15:42 supernit: delete empty first line
rnephew (Reviews Here) 2017/05/15 21:36:06 Done.
+ for conditions, reason in self._expectations.get(story.display_name, []):
+ for condition in conditions:
+ if condition.ShouldDisable(platform):
+ logging.info('%s is disabled on %s due to %s.',
+ story.display_name, condition, reason)
+ return reason
+ return None
+
+
+class _TestCondition(object):
+ def ShouldDisable(self, platform):
+ raise NotImplementedError
+
+ def __str__(self):
+ raise NotImplementedError
+
+
+class _TestConditionByPlatformList(_TestCondition):
+ def __init__(self, platforms, name):
+ self._platforms = platforms
+ self._name = name
+
+ def ShouldDisable(self, platform):
+ return platform.GetOSName() in self._platforms
+
+ def __str__(self):
+ return self._name
+
+
+class _AllTestCondition(_TestCondition):
+ def ShouldDisable(self, _):
+ return True
+
+ def __str__(self):
+ return 'All Platforms'
+
+
+class _NoBattOrTestCondition(_TestCondition):
+ # Example use case for NO_BATTOR test condition:
+ # If a trace is too long to be processed if it contains power data.
+ def ShouldDisable(self, platform):
+ return not platform.HasBattOrConnected()
+
+ def __str__(self):
+ return 'Platforms with no BattOr'
+
+
+ALL = _AllTestCondition()
+ALL_MAC = _TestConditionByPlatformList(['mac'], 'Mac Platforms')
+ALL_WIN = _TestConditionByPlatformList(['win'], 'Win Platforms')
+ALL_LINUX = _TestConditionByPlatformList(['linux'], 'Linux Platforms')
+ALL_ANDROID = _TestConditionByPlatformList(['android'], 'Android Platforms')
+ALL_DESKTOP = _TestConditionByPlatformList(
+ ['mac', 'linux', 'win'], 'Desktop Platforms')
+ALL_MOBILE = _TestConditionByPlatformList(['android'], 'Mobile Platforms')
+NO_BATTOR = _NoBattOrTestCondition()

Powered by Google App Engine
This is Rietveld 408576698