Upstream version 9.37.197.0
[platform/framework/web/crosswalk.git] / src / tools / telemetry / telemetry / test.py
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.
4
5 import logging
6 import optparse
7 import os
8 import shutil
9 import sys
10 import zipfile
11
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
22
23
24 Disabled = decorators.Disabled
25 Enabled = decorators.Enabled
26
27
28 class Test(command_line.Command):
29   """Base class for a Telemetry test or benchmark.
30
31   A test packages a PageTest/PageMeasurement and a PageSet together.
32   """
33   options = {}
34
35   @classmethod
36   def Name(cls):
37     name = cls.__module__.split('.')[-1]
38     if hasattr(cls, 'tag'):
39       name += '.' + cls.tag
40     if hasattr(cls, 'page_set'):
41       name += '.' + cls.page_set.Name()
42     return name
43
44   @classmethod
45   def AddCommandLineArgs(cls, parser):
46     cls.PageTestClass().AddCommandLineArgs(parser)
47
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)
52
53   @classmethod
54   def SetArgumentDefaults(cls, parser):
55     cls.PageTestClass().SetArgumentDefaults(parser)
56     parser.set_defaults(**cls.options)
57
58   @classmethod
59   def ProcessCommandLineArgs(cls, parser, args):
60     cls.PageTestClass().ProcessCommandLineArgs(parser, args)
61
62   def CustomizeBrowserOptions(self, options):
63     """Add browser options that are required by this benchmark."""
64
65   def Run(self, args):
66     """Run this test with the given options."""
67     self.CustomizeBrowserOptions(args.browser_options)
68
69     test = self.PageTestClass()()
70     test.__name__ = self.__class__.__name__
71
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
76
77     ps = self.CreatePageSet(args)
78     expectations = self.CreateExpectations(ps)
79
80     self._DownloadGeneratedProfileArchive(args)
81
82     results = page_test_results.PageTestResults()
83     try:
84       results = page_runner.Run(test, ps, expectations, args)
85     except page_test.TestNotSupportedOnPlatformFailure as failure:
86       logging.warning(str(failure))
87
88     results.PrintSummary()
89     return len(results.failures) + len(results.errors)
90
91   def _DownloadGeneratedProfileArchive(self, options):
92     """Download and extract profile directory archive if one exists."""
93     archive_name = getattr(self, 'generated_profile_archive', None)
94
95     # If attribute not specified, nothing to do.
96     if not archive_name:
97       return
98
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)
104       return
105
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))
113
114     try:
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)
124       else:
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)
130         logging.error(e)
131         sys.exit(-1)
132
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:
140       try:
141         f.extractall(os.path.dirname(generated_profile_archive_path))
142       except e:
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)
147         sys.exit(-1)
148
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
153
154   @classmethod
155   def PageTestClass(cls):
156     """Get the PageTest for this Test.
157
158     If the Test has no PageTest, raises NotImplementedError.
159     """
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__)
164     return cls.test
165
166   @classmethod
167   def PageSetClass(cls):
168     """Get the PageSet for this Test.
169
170     If the Test has no PageSet, raises NotImplementedError.
171     """
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__)
176     return cls.page_set
177
178   @classmethod
179   def CreatePageSet(cls, options):  # pylint: disable=W0613
180     """Get the page set this test will run on.
181
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.
184     """
185     return cls.PageSetClass()()
186
187   @classmethod
188   def CreateExpectations(cls, ps):  # pylint: disable=W0613
189     """Get the expectations this test will run with.
190
191     By default, it will create an empty expectations set. Override to generate
192     custom expectations.
193     """
194     if hasattr(cls, 'expectations'):
195       return cls.expectations
196     else:
197       return test_expectations.TestExpectations()
198
199
200 def AddCommandLineArgs(parser):
201   page_runner.AddCommandLineArgs(parser)
202
203
204 def ProcessCommandLineArgs(parser, args):
205   page_runner.ProcessCommandLineArgs(parser, args)