OLD | NEW |
| (Empty) |
1 #!/usr/bin/env python | |
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
3 # Use of this source code is governed by a BSD-style license that can be | |
4 # found in the LICENSE file. | |
5 | |
6 """A framework to run PyAuto HTML media tests. | |
7 | |
8 This PyAuto powered script plays media (video or audio) files (using the HTML5 | |
9 tag embedded in an HTML file). The parameters needed to run this test are | |
10 passed in the form of environment variables (such as the number of runs). | |
11 media_test_runner.py is used for generating these variables | |
12 (PyAuto does not support direct parameters). | |
13 """ | |
14 | |
15 import csv | |
16 import logging | |
17 import os | |
18 import time | |
19 | |
20 import pyauto_media | |
21 import pyauto | |
22 | |
23 from media_test_env_names import MediaTestEnvNames | |
24 from ui_perf_test_utils import UIPerfTestUtils | |
25 | |
26 | |
27 class MediaTestBase(pyauto.PyUITest): | |
28 """A base class for media related PyAuto tests. | |
29 | |
30 This class is meant to a base class for all media related Pyauto test and | |
31 provides useful functionality to run the test in conjunction with | |
32 player.html file, which contains basic html and JavaScipt for media test. | |
33 The main test method (ExecuteTest()) contains execution loops to get average | |
34 measured data over several runs with the same condition. This class also | |
35 contains several basic pre/post-processing methods that should be overridden. | |
36 """ | |
37 | |
38 # Default values used for default case. | |
39 DEFAULT_MEDIA_TAG_NAME = 'video' | |
40 DEFAULT_MEDIA_FILENAME = 'bear_silent.ogv' | |
41 DEFAULT_MEDIA_FILENAME_NICKNAME = 'bear_silent.ogv' | |
42 DEFAULT_PLAYER_HTML_URL_NICKNAME = 'local' | |
43 DEFAULT_NUMBER_OF_RUNS = 3 | |
44 # Timing out for checking if video has finished playing (in seconds). | |
45 # Currently, we do not have videos more than 1 minute. | |
46 TIMEOUT = 60 | |
47 # Instance variables that used across methods. | |
48 number_of_runs = 0 | |
49 url = '' | |
50 parameter_str = '' | |
51 times = [] | |
52 media_filename = '' | |
53 media_filename_nickname = '' | |
54 whole_test_scenarios = [] | |
55 reference_build = False | |
56 | |
57 def _GetMediaURLAndParameterString(self, media_filename): | |
58 """Get media url and parameter string. | |
59 | |
60 If media url is specified in environment variable, then it is used. | |
61 Otherwise, local media data directory is used for the url. | |
62 Parameter string is calculated based on the environment variables. | |
63 | |
64 Args: | |
65 media_filename: the file name for the media (video/audio) with extension. | |
66 | |
67 Returns: | |
68 a tuple of media_url (with proper query string) and a parameter string, | |
69 which is used for performance result display. | |
70 """ | |
71 # Read environment variables. | |
72 player_html_url = os.getenv(MediaTestEnvNames.PLAYER_HTML_URL_ENV_NAME, | |
73 'DEFAULT') | |
74 player_html_url_nickname = os.getenv( | |
75 MediaTestEnvNames.PLAYER_HTML_URL_NICKNAME_ENV_NAME, | |
76 self.DEFAULT_PLAYER_HTML_URL_NICKNAME) | |
77 extra_nickname = os.getenv(MediaTestEnvNames.EXTRA_NICKNAME_ENV_NAME, '') | |
78 | |
79 tag = os.getenv(MediaTestEnvNames.MEDIA_TAG_ENV_NAME, | |
80 self.DEFAULT_MEDIA_TAG_NAME) | |
81 query_dictionary = {'tag': tag, 'media': media_filename} | |
82 # This parameter tricks the media cache into thinking | |
83 # it's a new file every time. | |
84 # However, it looks like does not make much difference in | |
85 # performance. | |
86 if os.getenv(MediaTestEnvNames.ADD_T_PARAMETER_ENV_NAME): | |
87 query_dictionary['t'] = 'dummy' | |
88 track_file = os.getenv(MediaTestEnvNames.TRACK_FILE_ENV_NAME) | |
89 if track_file: | |
90 query_dictionary['track'] = track_file | |
91 query_dictionary['num_extra'] = ( | |
92 os.getenv(MediaTestEnvNames.N_EXTRA_PLAYERS_ENV_NAME, 0)) | |
93 if os.getenv(MediaTestEnvNames.JERKY_TEST_ENV_NAME): | |
94 query_dictionary['jerky'] = 'True' | |
95 query_str = '&'.join( | |
96 [k + '=' + str(v) for (k, v) in query_dictionary.items()]) | |
97 if player_html_url_nickname == self.DEFAULT_PLAYER_HTML_URL_NICKNAME: | |
98 # Default is local file under DataDir(). | |
99 file_url = self.GetFileURLForDataPath( | |
100 os.path.join('media', 'html', self.GetPlayerHTMLFileName())) | |
101 url = file_url + '?' + query_str | |
102 else: | |
103 url = player_html_url + '?' + query_str | |
104 parameter_str = '%s_%s_%s' % ( | |
105 extra_nickname, player_html_url_nickname, | |
106 os.getenv(MediaTestEnvNames.MEDIA_FILENAME_NICKNAME_ENV_NAME)) | |
107 return url, parameter_str | |
108 | |
109 def ReadTestScenarioFiles(self, test_scenario_filename): | |
110 """Read a test scenario CSV file with actions such as 'play'. | |
111 | |
112 In the CSV file, each row is a test scenario which consists of one | |
113 or more (time, action, action_argument) triples (time and action_argument | |
114 are in milliseconds). For example, the following CSV file contains 3 test | |
115 scenarios to be tested. | |
116 500, pause, 0 | |
117 1000, pause, 0, 2000, play, 0 | |
118 1000, seek, 0, 2000, ratechange, 2 | |
119 """ | |
120 test_scenarios = [] | |
121 rows = csv.reader(open(test_scenario_filename)) | |
122 for row in rows: | |
123 test_scenarios.append('|'.join(row)) | |
124 return test_scenarios | |
125 | |
126 def ExecuteTest(self): | |
127 """Test HTML5 Media Tag.""" | |
128 | |
129 def _VideoEndedOrErrorOut(): | |
130 """Determine if the video ended or there was an error when playing. | |
131 | |
132 When the video has finished playing or there is error in playing the | |
133 video (e.g, the video cannot be found), its title is updated by | |
134 player.html. | |
135 | |
136 Returns: | |
137 True if the video has ended or an error occurred. | |
138 """ | |
139 return (self.GetDOMValue('document.title').strip() == 'END' or | |
140 'ERROR' in self.GetDOMValue('document.title')) | |
141 | |
142 self.PreAllRunsProcess() | |
143 for run_counter in range(self.number_of_runs): | |
144 self.run_counter = run_counter | |
145 self.PreEachRunProcess(run_counter) | |
146 url = self.url | |
147 if self.whole_test_scenarios: | |
148 url += '&actions=' + self.whole_test_scenarios[run_counter] | |
149 logging.debug('Navigate to %s', url) | |
150 self.NavigateToURL(url) | |
151 self.WaitUntil(lambda: _VideoEndedOrErrorOut(), | |
152 self.TIMEOUT) | |
153 self.PostEachRunProcess(run_counter) | |
154 | |
155 self.PostAllRunsProcess() | |
156 | |
157 # A list of methods that should be overridden in the subclass. | |
158 # It is a good practice to call these methods even if these are | |
159 # overridden. | |
160 | |
161 def PreAllRunsProcess(self): | |
162 """A method to be executed before all runs. | |
163 | |
164 The default behavior is to read parameters for the tests and initialize | |
165 variables. | |
166 """ | |
167 self.media_filename = os.getenv(MediaTestEnvNames.MEDIA_FILENAME_ENV_NAME, | |
168 self.DEFAULT_MEDIA_FILENAME) | |
169 self.media_filename_nickname = os.getenv( | |
170 MediaTestEnvNames.MEDIA_FILENAME_NICKNAME_ENV_NAME, | |
171 self.DEFAULT_MEDIA_FILENAME_NICKNAME) | |
172 self.remove_first_result = os.getenv( | |
173 MediaTestEnvNames.REMOVE_FIRST_RESULT_ENV_NAME) | |
174 self.number_of_runs = int(os.getenv(MediaTestEnvNames.N_RUNS_ENV_NAME, | |
175 self.DEFAULT_NUMBER_OF_RUNS)) | |
176 self.url, self.parameter_str = self._GetMediaURLAndParameterString( | |
177 self.media_filename) | |
178 self.times = [] | |
179 self.reference_build = os.getenv( | |
180 MediaTestEnvNames.REFERENCE_BUILD_ENV_NAME, False) | |
181 test_scenario_filename = os.getenv( | |
182 MediaTestEnvNames.TEST_SCENARIO_FILE_ENV_NAME, '') | |
183 test_scenario = os.getenv( | |
184 MediaTestEnvNames.TEST_SCENARIO_ENV_NAME, '') | |
185 if test_scenario: | |
186 # Run test with the same action several times. | |
187 self.whole_test_scenarios = [test_scenario] * self.number_of_runs | |
188 if test_scenario_filename: | |
189 self.whole_test_scenarios = ( | |
190 self.ReadTestScenarioFiles(test_scenario_filename)) | |
191 # One run per test scenario. | |
192 self.number_of_runs = len(self.whole_test_scenarios) | |
193 | |
194 def PostAllRunsProcess(self): | |
195 """A method to execute after all runs. | |
196 | |
197 The default behavior is to do nothing | |
198 """ | |
199 pass | |
200 | |
201 def PreEachRunProcess(self, run_counter): | |
202 """A method to execute before each run. | |
203 | |
204 The default behavior is to record start time. | |
205 | |
206 Args: | |
207 run_counter: counter for each run. | |
208 """ | |
209 self.start = time.time() | |
210 | |
211 def PostEachRunProcess(self, run_counter): | |
212 """A method to execute after each run. | |
213 | |
214 The default behavior is to do nothing. | |
215 | |
216 Args: | |
217 run_counter: counter for each run. | |
218 """ | |
219 pass | |
220 | |
221 def GetPlayerHTMLFileName(self): | |
222 """A method to get the player HTML file name.""" | |
223 return 'media_playback.html' | |
224 | |
225 | |
226 if __name__ == '__main__': | |
227 pyauto_media.Main() | |
OLD | NEW |