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

Side by Side Diff: tools/telemetry/telemetry/page/record_wpr.py

Issue 374793002: Refactor of record_wpr.py (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: git rebase Created 6 years, 4 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 unified diff | Download patch
« no previous file with comments | « no previous file | tools/telemetry/telemetry/page/record_wpr_unittest.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright 2012 The Chromium Authors. All rights reserved. 2 # Copyright 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 import logging 5 import logging
6 import os 6 import os
7 import sys 7 import sys
8 import tempfile 8 import tempfile
9 import time 9 import time
10 10
11 from telemetry import benchmark 11 from telemetry import benchmark
12 from telemetry.core import browser_options 12 from telemetry.core import browser_options
13 from telemetry.core import discover 13 from telemetry.core import discover
14 from telemetry.core import wpr_modes 14 from telemetry.core import wpr_modes
15 from telemetry.page import page_measurement 15 from telemetry.page import page_measurement
16 from telemetry.page import page_runner 16 from telemetry.page import page_runner
17 from telemetry.page import page_set 17 from telemetry.page import page_set
18 from telemetry.page import page_test 18 from telemetry.page import page_test
19 from telemetry.page import profile_creator 19 from telemetry.page import profile_creator
20 from telemetry.page import test_expectations 20 from telemetry.page import test_expectations
21 from telemetry.page.actions import action_runner as action_runner_module
22 from telemetry.results import page_measurement_results 21 from telemetry.results import page_measurement_results
23 22
24 23
25 class RecordPage(page_test.PageTest): # pylint: disable=W0223 24 class RecorderPageTest(page_test.PageTest): # pylint: disable=W0223
26 def __init__(self, measurements): 25 def __init__(self, action_names):
27 # This class overwrites PageTest.Run, so that the test method name is not 26 super(RecorderPageTest, self).__init__()
28 # really used (except for throwing an exception if it doesn't exist). 27 self._action_names = action_names
29 super(RecordPage, self).__init__('Run') 28 self.page_test = None
30 self._action_names = set(
31 [measurement().action_name_to_run
32 for measurement in measurements.values()
33 if measurement().action_name_to_run])
34 self.test = None
35 29
36 def CanRunForPage(self, page): 30 def CanRunForPage(self, page):
37 return page.url.startswith('http') 31 return page.url.startswith('http')
38 32
39 def WillNavigateToPage(self, page, tab): 33 def WillNavigateToPage(self, page, tab):
40 """Override to ensure all resources are fetched from network.""" 34 """Override to ensure all resources are fetched from network."""
41 tab.ClearCache(force=False) 35 tab.ClearCache(force=False)
42 if self.test: 36 if self.page_test:
43 self.test.options = self.options 37 self.page_test.options = self.options
44 self.test.WillNavigateToPage(page, tab) 38 self.page_test.WillNavigateToPage(page, tab)
45 39
46 def DidNavigateToPage(self, page, tab): 40 def DidNavigateToPage(self, page, tab):
47 """Forward the call to the test.""" 41 if self.page_test:
48 if self.test: 42 self.page_test.DidNavigateToPage(page, tab)
49 self.test.DidNavigateToPage(page, tab) 43
44 def WillRunActions(self, page, tab):
45 if self.page_test:
46 self.page_test.WillRunActions(page, tab)
47
48 def DidRunActions(self, page, tab):
49 if self.page_test:
50 self.page_test.DidRunActions(page, tab)
51
52 def ValidatePage(self, page, tab, results):
53 if self.page_test:
54 self.page_test.ValidatePage(page, tab, results)
50 55
51 def RunPage(self, page, tab, results): 56 def RunPage(self, page, tab, results):
52 tab.WaitForDocumentReadyStateToBeComplete() 57 tab.WaitForDocumentReadyStateToBeComplete()
53 58
54 # When recording, sleep to catch any resources that load post-onload. 59 # When recording, sleep to catch any resources that load post-onload.
55 # TODO(tonyg): This should probably monitor resource timing for activity 60 # TODO(tonyg): This should probably monitor resource timing for activity
56 # and sleep until 2s since the last network event with some timeout like 61 # and sleep until 2s since the last network event with some timeout like
57 # 20s. We could wrap this up as WaitForNetworkIdle() and share with the 62 # 20s. We could wrap this up as WaitForNetworkIdle() and share with the
58 # speed index metric. 63 # speed index metric.
59 time.sleep(3) 64 time.sleep(3)
60 65
61 # Run the actions for all measurements. Reload the page between 66 # When running record_wpr, results is a GTestTestResults, so we create a
62 # actions. 67 # dummy PageMeasurementResults that implements the functions we use.
68 # TODO(chrishenry): Fix the need for a dummy_results object.
69 dummy_results = page_measurement_results.PageMeasurementResults()
70
71 if self.page_test:
72 self._action_name_to_run = self.page_test.action_name_to_run
73 self.page_test.RunPage(page, tab, dummy_results)
74 return
75
63 should_reload = False 76 should_reload = False
64 interactive = self.options and self.options.interactive 77 # Run the actions on the page for all available measurements.
65 for action_name in self._action_names: 78 for action_name in self._action_names:
79 # Skip this action if it is not defined
66 if not hasattr(page, action_name): 80 if not hasattr(page, action_name):
67 continue 81 continue
82 # Reload the page between actions to start with a clean slate.
68 if should_reload: 83 if should_reload:
69 self.RunNavigateSteps(page, tab) 84 self.RunNavigateSteps(page, tab)
70 action_runner = action_runner_module.ActionRunner(tab) 85 self._action_name_to_run = action_name
71 if interactive: 86 super(RecorderPageTest, self).RunPage(page, tab, dummy_results)
72 action_runner.PauseInteractive()
73 else:
74 self._RunMethod(page, action_name, action_runner)
75 should_reload = True 87 should_reload = True
76 88
77 # Run the PageTest's validator, so that we capture any additional resources 89 def RunNavigateSteps(self, page, tab):
78 # that are loaded by the test. 90 if self.page_test:
79 if self.test: 91 self.page_test.RunNavigateSteps(page, tab)
80 dummy_results = page_measurement_results.PageMeasurementResults() 92 else:
81 self.test.ValidatePage(page, tab, dummy_results) 93 super(RecorderPageTest, self).RunNavigateSteps(page, tab)
94
95
96 def FindAllActionNames(base_dir):
97 """Returns a set of of all action names used in our measurements."""
98 action_names = set()
99 # Get all PageMeasurements except for ProfileCreators (see crbug.com/319573)
100 for _, cls in discover.DiscoverClasses(
101 base_dir, base_dir, page_measurement.PageMeasurement).items():
102 if not issubclass(cls, profile_creator.ProfileCreator):
103 action_name = cls().action_name_to_run
104 if action_name:
105 action_names.add(action_name)
106 return action_names
107
108
109 def _MaybeGetInstanceOfClass(target, base_dir, cls):
110 if isinstance(target, cls):
111 return target
112 classes = discover.DiscoverClasses(base_dir, base_dir, cls,
113 index_by_class_name=True)
114 return classes[target]() if target in classes else None
115
116
117 class WprRecorder(object):
118
119 def __init__(self, base_dir, target, extra_args=None):
120 action_names_to_run = FindAllActionNames(base_dir)
121 self._record_page_test = RecorderPageTest(action_names_to_run)
122 self._temp_target_wpr_file_path = tempfile.mkstemp()[1]
123 self._options = self._CreateOptions()
124
125 self._benchmark = _MaybeGetInstanceOfClass(target, base_dir,
126 benchmark.Benchmark)
127 if self._benchmark is not None:
128 self._record_page_test.page_test = self._benchmark.test()
129 self._parser = self._options.CreateParser(usage='%prog <PageSet|Benchmark>')
130 self._AddCommandLineArgs()
131 self._ParseArgs(extra_args)
132 self._ProcessCommandLineArgs()
133 self._page_set = self._GetPageSet(base_dir, target)
134
135 @property
136 def options(self):
137 return self._options
138
139 def _CreateOptions(self):
140 options = browser_options.BrowserFinderOptions()
141 options.browser_options.wpr_mode = wpr_modes.WPR_RECORD
142 options.browser_options.no_proxy_server = True
143 return options
144
145 def _AddCommandLineArgs(self):
146 page_runner.AddCommandLineArgs(self._parser)
147 if self._benchmark is not None:
148 self._benchmark.AddCommandLineArgs(self._parser)
149 self._benchmark.SetArgumentDefaults(self._parser)
150
151 def _ParseArgs(self, extra_args=None):
152 args = sys.argv[1:]
153 if extra_args is not None:
154 args += extra_args
155 self._parser.parse_args(args)
156
157 def _ProcessCommandLineArgs(self):
158 page_runner.ProcessCommandLineArgs(self._parser, self._options)
159 if self._benchmark is not None:
160 self._benchmark.ProcessCommandLineArgs(self._parser, self._options)
161
162 def _GetPageSet(self, base_dir, target):
163 if self._benchmark is not None:
164 return self._benchmark.CreatePageSet(self._options)
165 ps = _MaybeGetInstanceOfClass(target, base_dir, page_set.PageSet)
166 if ps is None:
167 self._parser.print_usage()
168 sys.exit(1)
169 return ps
170
171 def Record(self):
172 self._page_set.wpr_archive_info.AddNewTemporaryRecording(
173 self._temp_target_wpr_file_path)
174 self._record_page_test.CustomizeBrowserOptions(self._options)
175 return page_runner.Run(self._record_page_test, self._page_set,
176 test_expectations.TestExpectations(), self._options)
177
178 def HandleResults(self, results):
179 if results.failures or results.skipped:
180 logging.warning('Some pages failed and/or were skipped. The recording '
181 'has not been updated for these pages.')
182 results.PrintSummary()
183
184 if results.successes:
185 # Update the metadata for the pages which were recorded.
186 self._page_set.wpr_archive_info.AddRecordedPages(results.successes)
187 else:
188 os.remove(self._temp_target_wpr_file_path)
82 189
83 190
84 def Main(base_dir): 191 def Main(base_dir):
85 measurements = {
86 n: cls for n, cls in discover.DiscoverClasses(
87 base_dir, base_dir, page_measurement.PageMeasurement).items()
88 # Filter out unneeded ProfileCreators (crbug.com/319573).
89 if not issubclass(cls, profile_creator.ProfileCreator)
90 }
91 tests = discover.DiscoverClasses(base_dir, base_dir, benchmark.Benchmark,
92 index_by_class_name=True)
93
94 options = browser_options.BrowserFinderOptions()
95 parser = options.CreateParser('%prog <PageSet|Test|URL>')
96 page_runner.AddCommandLineArgs(parser)
97
98 recorder = RecordPage(measurements)
99 recorder.AddCommandLineArgs(parser)
100
101 quick_args = [a for a in sys.argv[1:] if not a.startswith('-')] 192 quick_args = [a for a in sys.argv[1:] if not a.startswith('-')]
102 if len(quick_args) != 1: 193 if len(quick_args) != 1:
103 parser.print_usage() 194 print >> sys.stderr, 'Usage: record_wpr <PageSet|Benchmark>\n'
104 sys.exit(1) 195 sys.exit(1)
105 target = quick_args[0] 196 target = quick_args.pop()
106 if target in tests: 197 wpr_recorder = WprRecorder(base_dir, target)
107 recorder.test = tests[target]().test() 198 results = wpr_recorder.Record()
108 recorder.test.AddCommandLineArgs(parser) 199 wpr_recorder.HandleResults(results)
109 recorder.test.SetArgumentDefaults(parser)
110 parser.parse_args()
111 recorder.test.ProcessCommandLineArgs(parser, options)
112 ps = tests[target]().CreatePageSet(options)
113 elif discover.IsPageSetFile(target):
114 parser.parse_args()
115 ps = page_set.PageSet.FromFile(target)
116 else:
117 parser.print_usage()
118 sys.exit(1)
119
120 page_runner.ProcessCommandLineArgs(parser, options)
121 recorder.ProcessCommandLineArgs(parser, options)
122
123 expectations = test_expectations.TestExpectations()
124
125 # Set the archive path to something temporary.
126 temp_target_wpr_file_path = tempfile.mkstemp()[1]
127 ps.wpr_archive_info.AddNewTemporaryRecording(temp_target_wpr_file_path)
128
129 # Do the actual recording.
130 options.browser_options.wpr_mode = wpr_modes.WPR_RECORD
131 options.browser_options.no_proxy_server = True
132 recorder.CustomizeBrowserOptions(options)
133 results = page_runner.Run(recorder, ps, expectations, options)
134
135 if results.failures:
136 logging.warning('Some pages failed. The recording has not been updated for '
137 'these pages.')
138 logging.warning('Failed pages:\n%s', '\n'.join(
139 p.display_name for p in results.pages_that_had_failures))
140
141 if results.skipped:
142 logging.warning('Some pages were skipped. The recording has not been '
143 'updated for these pages.')
144 logging.warning('Skipped pages:\n%s', '\n'.join(
145 p.display_name for p in zip(*results.skipped)[0]))
146
147 if results.successes:
148 # Update the metadata for the pages which were recorded.
149 ps.wpr_archive_info.AddRecordedPages(results.successes)
150 else:
151 os.remove(temp_target_wpr_file_path)
152
153 return min(255, len(results.failures)) 200 return min(255, len(results.failures))
OLDNEW
« no previous file with comments | « no previous file | tools/telemetry/telemetry/page/record_wpr_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698