Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / tools / telemetry / telemetry / test.py
1 # Copyright (c) 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 import logging
6 import os
7 import shutil
8 import sys
9 import zipfile
10
11 from telemetry import decorators
12 from telemetry.core import browser_finder
13 from telemetry.core import repeat_options
14 from telemetry.core import util
15 from telemetry.page import page_runner
16 from telemetry.page import cloud_storage
17 from telemetry.page import page_set
18 from telemetry.page import page_test
19 from telemetry.page import test_expectations
20
21
22 Disabled = decorators.Disabled
23 Enabled = decorators.Enabled
24
25
26 class Test(object):
27   """Base class for a Telemetry test or benchmark.
28
29   A test packages a PageTest/PageMeasurement and a PageSet together.
30   """
31   options = {}
32
33   @classmethod
34   def GetName(cls):
35     name = cls.__module__.split('.')[-1]
36     if hasattr(cls, 'tag'):
37       name += '.' + cls.tag
38     if hasattr(cls, 'page_set'):
39       name += '.' + os.path.basename(os.path.splitext(cls.page_set)[0])
40     return name
41
42   def Run(self, options):
43     """Run this test with the given options."""
44     assert hasattr(self, 'test'), 'This test has no "test" attribute.'
45     assert issubclass(self.test, page_test.PageTest), (
46             '"%s" is not a PageTest.' % self.test.__name__)
47
48     for key, value in self.options.iteritems():
49       setattr(options, key, value)
50
51     if hasattr(self, '_disabled_strings'):
52       self.test._disabled_strings = self._disabled_strings
53     if hasattr(self, '_enabled_strings'):
54       self.test._enabled_strings = self._enabled_strings
55
56     options.repeat_options = self._CreateRepeatOptions(options)
57     self.CustomizeBrowserOptions(options)
58
59     test = self.test()
60     test.__name__ = self.__class__.__name__
61     ps = self.CreatePageSet(options)
62     expectations = self.CreateExpectations(ps)
63
64     # Ensure the test's default options are set if needed.
65     parser = options.CreateParser()
66     test.AddCommandLineOptions(parser)
67     options.MergeDefaultValues(parser.get_default_values())
68
69     self._DownloadGeneratedProfileArchive(options)
70
71     results = page_runner.Run(test, ps, expectations, options)
72     results.PrintSummary()
73     return len(results.failures) + len(results.errors)
74
75   def _CreateRepeatOptions(self, options):
76     return repeat_options.RepeatOptions(
77         getattr(options, 'page_repeat_secs', None),
78         getattr(options, 'pageset_repeat_secs', None),
79         getattr(options, 'page_repeat_iters', 1),
80         getattr(options, 'pageset_repeat_iters', 1),
81       )
82
83   def _DownloadGeneratedProfileArchive(self, options):
84     """Download and extract profile directory archive if one exists."""
85     archive_name = getattr(self, 'generated_profile_archive', None)
86
87     # If attribute not specified, nothing to do.
88     if not archive_name:
89       return
90
91     # If profile dir specified on command line, nothing to do.
92     if options.browser_options.profile_dir:
93       logging.warning("Profile directory specified on command line: %s, this"
94           "overrides the benchmark's default profile directory.",
95           options.browser_options.profile_dir)
96       return
97
98     # Download profile directory from cloud storage.
99     found_browser = browser_finder.FindBrowser(options)
100     test_data_dir = os.path.join(util.GetChromiumSrcDir(), 'tools', 'perf',
101         'generated_profiles',
102         found_browser.target_os)
103     generated_profile_archive_path = os.path.normpath(
104         os.path.join(test_data_dir, archive_name))
105
106     try:
107       cloud_storage.GetIfChanged(generated_profile_archive_path,
108           cloud_storage.PUBLIC_BUCKET)
109     except (cloud_storage.CredentialsError,
110             cloud_storage.PermissionError) as e:
111       if os.path.exists(generated_profile_archive_path):
112         # If the profile directory archive exists, assume the user has their
113         # own local copy simply warn.
114         logging.warning('Could not download Profile archive: %s',
115             generated_profile_archive_path)
116       else:
117         # If the archive profile directory doesn't exist, this is fatal.
118         logging.error('Can not run without required profile archive: %s. '
119                       'If you believe you have credentials, follow the '
120                       'instructions below.',
121                       generated_profile_archive_path)
122         logging.error(e)
123         sys.exit(1)
124
125     # Unzip profile directory.
126     extracted_profile_dir_path = (
127         os.path.splitext(generated_profile_archive_path)[0])
128     if not os.path.isfile(generated_profile_archive_path):
129       raise Exception("Profile directory archive not downloaded: ",
130           generated_profile_archive_path)
131     with zipfile.ZipFile(generated_profile_archive_path) as f:
132       try:
133         f.extractall(os.path.dirname(generated_profile_archive_path))
134       except e:
135         # Cleanup any leftovers from unzipping.
136         if os.path.exists(extracted_profile_dir_path):
137           shutil.rmtree(extracted_profile_dir_path)
138         logging.error("Error extracting profile directory zip file: %s", e)
139         sys.exit(1)
140
141     # Run with freshly extracted profile directory.
142     logging.info("Using profile archive directory: %s",
143         extracted_profile_dir_path)
144     options.browser_options.profile_dir = extracted_profile_dir_path
145
146   def CreatePageSet(self, options):  # pylint: disable=W0613
147     """Get the page set this test will run on.
148
149     By default, it will create a page set from the file at this test's
150     page_set attribute. Override to generate a custom page set.
151     """
152     assert hasattr(self, 'page_set'), 'This test has no "page_set" attribute.'
153     return page_set.PageSet.FromFile(
154         os.path.join(util.GetBaseDir(), self.page_set))
155
156   def CreateExpectations(self, ps):  # pylint: disable=W0613
157     """Get the expectations this test will run with.
158
159     By default, it will create an empty expectations set. Override to generate
160     custom expectations.
161     """
162     if hasattr(self, 'expectations'):
163       return self.expectations
164     else:
165       return test_expectations.TestExpectations()
166
167   @staticmethod
168   def AddCommandLineOptions(parser):
169     page_runner.AddCommandLineOptions(parser)
170
171   @staticmethod
172   def AddTestCommandLineOptions(parser):
173     """Override to accept custom command line options."""
174     pass
175
176   def CustomizeBrowserOptions(self, options):
177     """Add browser options that are required by this benchmark."""
178     pass