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.
12 from telemetry import decorators
13 from telemetry.core import browser_finder
14 from telemetry.core import command_line
15 from telemetry.core import util
16 from telemetry.page import page_runner
17 from telemetry.page import cloud_storage
18 from telemetry.page import page_set
19 from telemetry.page import page_test
20 from telemetry.page import test_expectations
21 from telemetry.results import page_test_results
24 Disabled = decorators.Disabled
25 Enabled = decorators.Enabled
28 class Test(command_line.Command):
29 """Base class for a Telemetry test or benchmark.
31 A test packages a PageTest/PageMeasurement and a PageSet together.
37 name = cls.__module__.split('.')[-1]
38 if hasattr(cls, 'tag'):
40 if hasattr(cls, 'page_set'):
41 name += '.' + cls.page_set.Name()
45 def AddCommandLineArgs(cls, parser):
46 cls.PageTestClass().AddCommandLineArgs(parser)
48 if hasattr(cls, 'AddTestCommandLineArgs'):
49 group = optparse.OptionGroup(parser, '%s test options' % cls.Name())
50 cls.AddTestCommandLineArgs(group)
51 parser.add_option_group(group)
54 def SetArgumentDefaults(cls, parser):
55 cls.PageTestClass().SetArgumentDefaults(parser)
56 parser.set_defaults(**cls.options)
59 def ProcessCommandLineArgs(cls, parser, args):
60 cls.PageTestClass().ProcessCommandLineArgs(parser, args)
62 def CustomizeBrowserOptions(self, options):
63 """Add browser options that are required by this benchmark."""
66 """Run this test with the given options."""
67 self.CustomizeBrowserOptions(args.browser_options)
69 test = self.PageTestClass()()
70 test.__name__ = self.__class__.__name__
72 if hasattr(self, '_disabled_strings'):
73 test._disabled_strings = self._disabled_strings
74 if hasattr(self, '_enabled_strings'):
75 test._enabled_strings = self._enabled_strings
77 ps = self.CreatePageSet(args)
78 expectations = self.CreateExpectations(ps)
80 self._DownloadGeneratedProfileArchive(args)
82 results = page_test_results.PageTestResults()
84 results = page_runner.Run(test, ps, expectations, args)
85 except page_test.TestNotSupportedOnPlatformFailure as failure:
86 logging.warning(str(failure))
88 results.PrintSummary()
89 return len(results.failures) + len(results.errors)
91 def _DownloadGeneratedProfileArchive(self, options):
92 """Download and extract profile directory archive if one exists."""
93 archive_name = getattr(self, 'generated_profile_archive', None)
95 # If attribute not specified, nothing to do.
99 # If profile dir specified on command line, nothing to do.
100 if options.browser_options.profile_dir:
101 logging.warning("Profile directory specified on command line: %s, this"
102 "overrides the benchmark's default profile directory.",
103 options.browser_options.profile_dir)
106 # Download profile directory from cloud storage.
107 found_browser = browser_finder.FindBrowser(options)
108 test_data_dir = os.path.join(util.GetChromiumSrcDir(), 'tools', 'perf',
109 'generated_profiles',
110 found_browser.target_os)
111 generated_profile_archive_path = os.path.normpath(
112 os.path.join(test_data_dir, archive_name))
115 cloud_storage.GetIfChanged(generated_profile_archive_path,
116 cloud_storage.PUBLIC_BUCKET)
117 except (cloud_storage.CredentialsError,
118 cloud_storage.PermissionError) as e:
119 if os.path.exists(generated_profile_archive_path):
120 # If the profile directory archive exists, assume the user has their
121 # own local copy simply warn.
122 logging.warning('Could not download Profile archive: %s',
123 generated_profile_archive_path)
125 # If the archive profile directory doesn't exist, this is fatal.
126 logging.error('Can not run without required profile archive: %s. '
127 'If you believe you have credentials, follow the '
128 'instructions below.',
129 generated_profile_archive_path)
133 # Unzip profile directory.
134 extracted_profile_dir_path = (
135 os.path.splitext(generated_profile_archive_path)[0])
136 if not os.path.isfile(generated_profile_archive_path):
137 raise Exception("Profile directory archive not downloaded: ",
138 generated_profile_archive_path)
139 with zipfile.ZipFile(generated_profile_archive_path) as f:
141 f.extractall(os.path.dirname(generated_profile_archive_path))
143 # Cleanup any leftovers from unzipping.
144 if os.path.exists(extracted_profile_dir_path):
145 shutil.rmtree(extracted_profile_dir_path)
146 logging.error("Error extracting profile directory zip file: %s", e)
149 # Run with freshly extracted profile directory.
150 logging.info("Using profile archive directory: %s",
151 extracted_profile_dir_path)
152 options.browser_options.profile_dir = extracted_profile_dir_path
155 def PageTestClass(cls):
156 """Get the PageTest for this Test.
158 If the Test has no PageTest, raises NotImplementedError.
160 if not hasattr(cls, 'test'):
161 raise NotImplementedError('This test has no "test" attribute.')
162 if not issubclass(cls.test, page_test.PageTest):
163 raise TypeError('"%s" is not a PageTest.' % cls.test.__name__)
167 def PageSetClass(cls):
168 """Get the PageSet for this Test.
170 If the Test has no PageSet, raises NotImplementedError.
172 if not hasattr(cls, 'page_set'):
173 raise NotImplementedError('This test has no "page_set" attribute.')
174 if not issubclass(cls.page_set, page_set.PageSet):
175 raise TypeError('"%s" is not a PageSet.' % cls.page_set.__name__)
179 def CreatePageSet(cls, options): # pylint: disable=W0613
180 """Get the page set this test will run on.
182 By default, it will create a page set from the file at this test's
183 page_set attribute. Override to generate a custom page set.
185 return cls.PageSetClass()()
188 def CreateExpectations(cls, ps): # pylint: disable=W0613
189 """Get the expectations this test will run with.
191 By default, it will create an empty expectations set. Override to generate
194 if hasattr(cls, 'expectations'):
195 return cls.expectations
197 return test_expectations.TestExpectations()
200 def AddCommandLineArgs(parser):
201 page_runner.AddCommandLineArgs(parser)
204 def ProcessCommandLineArgs(parser, args):
205 page_runner.ProcessCommandLineArgs(parser, args)