1 # Copyright 2012 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.
8 from telemetry import benchmark
9 from telemetry.core import browser_options
10 from telemetry.core import discover
11 from telemetry.core import util
12 from telemetry.core import wpr_modes
13 from telemetry.page import page_runner
14 from telemetry.page import page_set
15 from telemetry.page import page_test
16 from telemetry.page import profile_creator
17 from telemetry.page import test_expectations
18 from telemetry.results import results_options
21 class RecorderPageTest(page_test.PageTest): # pylint: disable=W0223
22 def __init__(self, action_names):
23 super(RecorderPageTest, self).__init__()
24 self._action_names = action_names
27 def CanRunForPage(self, page):
28 return page.url.startswith('http')
30 def WillNavigateToPage(self, page, tab):
31 """Override to ensure all resources are fetched from network."""
32 tab.ClearCache(force=False)
34 self.page_test.options = self.options
35 self.page_test.WillNavigateToPage(page, tab)
37 def DidNavigateToPage(self, page, tab):
39 self.page_test.DidNavigateToPage(page, tab)
41 def WillRunActions(self, page, tab):
43 self.page_test.WillRunActions(page, tab)
45 def DidRunActions(self, page, tab):
47 self.page_test.DidRunActions(page, tab)
49 def ValidateAndMeasurePage(self, page, tab, results):
51 self.page_test.ValidateAndMeasurePage(page, tab, results)
53 def RunPage(self, page, tab, results):
54 tab.WaitForDocumentReadyStateToBeComplete()
55 util.WaitFor(tab.HasReachedQuiescence, 30)
58 self._action_name_to_run = self.page_test.action_name_to_run
59 self.page_test.RunPage(page, tab, results)
63 # Run the actions on the page for all available measurements.
64 for action_name in self._action_names:
65 # Skip this action if it is not defined
66 if not hasattr(page, action_name):
68 # Reload the page between actions to start with a clean slate.
70 self.RunNavigateSteps(page, tab)
71 self._action_name_to_run = action_name
72 super(RecorderPageTest, self).RunPage(page, tab, results)
75 def RunNavigateSteps(self, page, tab):
77 self.page_test.RunNavigateSteps(page, tab)
79 super(RecorderPageTest, self).RunNavigateSteps(page, tab)
82 def FindAllActionNames(base_dir):
83 """Returns a set of of all action names used in our measurements."""
85 # Get all PageTests except for ProfileCreators (see crbug.com/319573)
86 for _, cls in discover.DiscoverClasses(
87 base_dir, base_dir, page_test.PageTest).items():
88 if not issubclass(cls, profile_creator.ProfileCreator):
89 action_name = cls().action_name_to_run
91 action_names.add(action_name)
95 def _MaybeGetInstanceOfClass(target, base_dir, cls):
96 if isinstance(target, cls):
98 classes = discover.DiscoverClasses(base_dir, base_dir, cls,
99 index_by_class_name=True)
100 return classes[target]() if target in classes else None
103 class WprRecorder(object):
105 def __init__(self, base_dir, target, args=None):
106 action_names_to_run = FindAllActionNames(base_dir)
107 self._record_page_test = RecorderPageTest(action_names_to_run)
108 self._options = self._CreateOptions()
110 self._benchmark = _MaybeGetInstanceOfClass(target, base_dir,
112 if self._benchmark is not None:
113 self._record_page_test.page_test = self._benchmark.test()
114 self._parser = self._options.CreateParser(usage='%prog <PageSet|Benchmark>')
115 self._AddCommandLineArgs()
116 self._ParseArgs(args)
117 self._ProcessCommandLineArgs()
118 self._page_set = self._GetPageSet(base_dir, target)
124 def _CreateOptions(self):
125 options = browser_options.BrowserFinderOptions()
126 options.browser_options.wpr_mode = wpr_modes.WPR_RECORD
127 options.browser_options.no_proxy_server = True
130 def CreateResults(self):
131 if self._benchmark is not None:
132 benchmark_metadata = self._benchmark.GetMetadata()
134 benchmark_metadata = benchmark.BenchmarkMetadata('record_wpr')
136 return results_options.CreateResults(benchmark_metadata, self._options)
138 def _AddCommandLineArgs(self):
139 page_runner.AddCommandLineArgs(self._parser)
140 if self._benchmark is not None:
141 self._benchmark.AddCommandLineArgs(self._parser)
142 self._benchmark.SetArgumentDefaults(self._parser)
143 self._SetArgumentDefaults()
145 def _SetArgumentDefaults(self):
146 self._parser.set_defaults(**{'output_format': 'none'})
148 def _ParseArgs(self, args=None):
149 args_to_parse = sys.argv[1:] if args is None else args
150 self._parser.parse_args(args_to_parse)
152 def _ProcessCommandLineArgs(self):
153 page_runner.ProcessCommandLineArgs(self._parser, self._options)
154 if self._benchmark is not None:
155 self._benchmark.ProcessCommandLineArgs(self._parser, self._options)
157 def _GetPageSet(self, base_dir, target):
158 if self._benchmark is not None:
159 return self._benchmark.CreatePageSet(self._options)
160 ps = _MaybeGetInstanceOfClass(target, base_dir, page_set.PageSet)
162 self._parser.print_usage()
166 def Record(self, results):
167 self._page_set.wpr_archive_info.AddNewTemporaryRecording()
168 self._record_page_test.CustomizeBrowserOptions(self._options)
169 page_runner.Run(self._record_page_test, self._page_set,
170 test_expectations.TestExpectations(), self._options, results)
172 def HandleResults(self, results):
173 if results.failures or results.skipped_values:
174 logging.warning('Some pages failed and/or were skipped. The recording '
175 'has not been updated for these pages.')
176 results.PrintSummary()
177 self._page_set.wpr_archive_info.AddRecordedPages(
178 results.pages_that_succeeded)
182 quick_args = [a for a in sys.argv[1:] if not a.startswith('-')]
183 if len(quick_args) != 1:
184 print >> sys.stderr, 'Usage: record_wpr <PageSet|Benchmark>\n'
186 target = quick_args.pop()
187 wpr_recorder = WprRecorder(base_dir, target)
188 results = wpr_recorder.CreateResults()
189 wpr_recorder.Record(results)
190 wpr_recorder.HandleResults(results)
191 return min(255, len(results.failures))