OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # | 2 # |
3 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 3 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
6 | 6 |
7 """Wrapper for tests that are run on builders.""" | 7 """Wrapper for tests that are run on builders.""" |
8 | 8 |
9 import fileinput | 9 import fileinput |
10 import optparse | 10 import optparse |
11 import os | 11 import os |
12 import re | 12 import re |
13 import sys | 13 import sys |
14 import traceback | 14 import traceback |
15 import urllib | 15 import urllib |
16 import HTMLParser | 16 import HTMLParser |
17 | 17 |
18 sys.path.append(os.path.join(os.path.dirname(__file__), '../lib')) | 18 import constants |
19 from cros_build_lib import Info | 19 sys.path.append(constants.SOURCE_ROOT) |
20 from cros_build_lib import ReinterpretPathForChroot | 20 import chromite.lib.cros_build_lib as cros_lib |
21 from cros_build_lib import RunCommand | |
22 from cros_build_lib import Warning | |
23 | 21 |
24 _IMAGE_TO_EXTRACT = 'chromiumos_test_image.bin' | 22 _IMAGE_TO_EXTRACT = 'chromiumos_test_image.bin' |
25 _NEW_STYLE_VERSION = '0.9.131.0' | 23 _NEW_STYLE_VERSION = '0.9.131.0' |
26 | 24 |
27 class HTMLDirectoryParser(HTMLParser.HTMLParser): | 25 class HTMLDirectoryParser(HTMLParser.HTMLParser): |
28 """HTMLParser for parsing the default apache file index.""" | 26 """HTMLParser for parsing the default apache file index.""" |
29 | 27 |
30 def __init__(self, regex): | 28 def __init__(self, regex): |
31 HTMLParser.HTMLParser.__init__(self) | 29 HTMLParser.HTMLParser.__init__(self) |
32 self.regex_object = re.compile(regex) | 30 self.regex_object = re.compile(regex) |
(...skipping 23 matching lines...) Expand all Loading... |
56 | 54 |
57 The default boot.desc from another system is specific to the directory | 55 The default boot.desc from another system is specific to the directory |
58 it was created in. This modifies the boot description to be compatiable | 56 it was created in. This modifies the boot description to be compatiable |
59 with the download folder. | 57 with the download folder. |
60 | 58 |
61 Args: | 59 Args: |
62 download_folder: Absoulte path to the download folder. | 60 download_folder: Absoulte path to the download folder. |
63 redirect_file: For testing. Where to copy new boot desc. | 61 redirect_file: For testing. Where to copy new boot desc. |
64 """ | 62 """ |
65 boot_desc_path = os.path.join(download_folder, 'boot.desc') | 63 boot_desc_path = os.path.join(download_folder, 'boot.desc') |
66 in_chroot_folder = ReinterpretPathForChroot(download_folder) | 64 in_chroot_folder = cros_lib.ReinterpretPathForChroot(download_folder) |
67 | 65 |
68 for line in fileinput.input(boot_desc_path, inplace=1): | 66 for line in fileinput.input(boot_desc_path, inplace=1): |
69 # Has to be done here to get changes to sys.stdout from fileinput.input. | 67 # Has to be done here to get changes to sys.stdout from fileinput.input. |
70 if not redirect_file: | 68 if not redirect_file: |
71 redirect_file = sys.stdout | 69 redirect_file = sys.stdout |
72 split_line = line.split('=') | 70 split_line = line.split('=') |
73 if len(split_line) > 1: | 71 if len(split_line) > 1: |
74 var_part = split_line[0] | 72 var_part = split_line[0] |
75 potential_path = split_line[1].replace('"', '').strip() | 73 potential_path = split_line[1].replace('"', '').strip() |
76 | 74 |
77 if potential_path.startswith('/home') and not 'output_dir' in var_part: | 75 if potential_path.startswith('/home') and not 'output_dir' in var_part: |
78 new_path = os.path.join(in_chroot_folder, | 76 new_path = os.path.join(in_chroot_folder, |
79 os.path.basename(potential_path)) | 77 os.path.basename(potential_path)) |
80 new_line = '%s="%s"' % (var_part, new_path) | 78 new_line = '%s="%s"' % (var_part, new_path) |
81 Info('Replacing line %s with %s' % (line, new_line)) | 79 cros_lib.Info('Replacing line %s with %s' % (line, new_line)) |
82 redirect_file.write('%s\n' % new_line) | 80 redirect_file.write('%s\n' % new_line) |
83 continue | 81 continue |
84 elif 'output_dir' in var_part: | 82 elif 'output_dir' in var_part: |
85 # Special case for output_dir. | 83 # Special case for output_dir. |
86 new_line = '%s="%s"' % (var_part, in_chroot_folder) | 84 new_line = '%s="%s"' % (var_part, in_chroot_folder) |
87 Info('Replacing line %s with %s' % (line, new_line)) | 85 cros_lib.Info('Replacing line %s with %s' % (line, new_line)) |
88 redirect_file.write('%s\n' % new_line) | 86 redirect_file.write('%s\n' % new_line) |
89 continue | 87 continue |
90 | 88 |
91 # Line does not need to be modified. | 89 # Line does not need to be modified. |
92 redirect_file.write(line) | 90 redirect_file.write(line) |
93 | 91 |
94 fileinput.close() | 92 fileinput.close() |
95 | 93 |
96 | 94 |
97 def _GreaterVersion(version_a, version_b): | 95 def _GreaterVersion(version_a, version_b): |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 """ | 133 """ |
136 zip_base = os.path.join(zip_server_base, channel, board) | 134 zip_base = os.path.join(zip_server_base, channel, board) |
137 latest_version = GetLatestLinkFromPage(zip_base, '\d+\.\d+\.\d+\.\d+/') | 135 latest_version = GetLatestLinkFromPage(zip_base, '\d+\.\d+\.\d+\.\d+/') |
138 | 136 |
139 zip_dir = os.path.join(zip_base, latest_version) | 137 zip_dir = os.path.join(zip_base, latest_version) |
140 zip_name = GetLatestLinkFromPage(zip_dir, | 138 zip_name = GetLatestLinkFromPage(zip_dir, |
141 'ChromeOS-\d+\.\d+\.\d+\.\d+-.*\.zip') | 139 'ChromeOS-\d+\.\d+\.\d+\.\d+-.*\.zip') |
142 return os.path.join(zip_dir, zip_name) | 140 return os.path.join(zip_dir, zip_name) |
143 | 141 |
144 | 142 |
145 def GetLatestZipUrl(board, channel, latest_url_base, zip_server_base): | 143 def GetLatestZipUrl(board, channel, zip_server_base): |
146 """Returns the url of the latest image zip for the given arguments. | 144 """Returns the url of the latest image zip for the given arguments. |
147 | 145 |
| 146 If the latest does not exist, tries to find the rc equivalent. |
| 147 |
148 Args: | 148 Args: |
149 board: board for the image zip. | 149 board: board for the image zip. |
150 channel: channel for the image zip. | 150 channel: channel for the image zip. |
151 latest_url_base: base url for latest links. | |
152 zip_server_base: base url for zipped images. | 151 zip_server_base: base url for zipped images. |
153 """ | 152 """ |
154 if latest_url_base: | |
155 try: | |
156 # Grab the latest image info. | |
157 latest_file_url = os.path.join(latest_url_base, channel, | |
158 'LATEST-%s' % board) | |
159 latest_image_file = urllib.urlopen(latest_file_url) | |
160 latest_image = latest_image_file.read() | |
161 latest_image_file.close() | |
162 # Convert bin.gz into zip. | |
163 latest_image = latest_image.replace('.bin.gz', '.zip') | |
164 version = latest_image.split('-')[1] | |
165 zip_base = os.path.join(zip_server_base, channel, board) | |
166 return os.path.join(zip_base, version, latest_image) | |
167 except IOError: | |
168 Warning(('Could not use latest link provided, defaulting to parsing' | |
169 ' latest from zip url base.')) | |
170 | |
171 try: | 153 try: |
172 return GetNewestLinkFromZipBase(board, channel, zip_server_base) | 154 return GetNewestLinkFromZipBase(board, channel, zip_server_base) |
173 except: | 155 except: |
174 Warning('Failed to get url from standard zip base. Trying rc.') | 156 cros_lib.Warning('Failed to get url from standard zip base. Trying rc.') |
175 return GetNewestLinkFromZipBase(board + '-rc', channel, zip_server_base) | 157 return GetNewestLinkFromZipBase(board + '-rc', channel, zip_server_base) |
176 | 158 |
177 | 159 |
178 def GrabZipAndExtractImage(zip_url, download_folder, image_name) : | 160 def GrabZipAndExtractImage(zip_url, download_folder, image_name) : |
179 """Downloads the zip and extracts the given image. | 161 """Downloads the zip and extracts the given image. |
180 | 162 |
181 Doesn't re-download if matching version found already in download folder. | 163 Doesn't re-download if matching version found already in download folder. |
182 Args: | 164 Args: |
183 zip_url - url for the image. | 165 zip_url - url for the image. |
184 download_folder - download folder to store zip file and extracted images. | 166 download_folder - download folder to store zip file and extracted images. |
185 image_name - name of the image to extract from the zip file. | 167 image_name - name of the image to extract from the zip file. |
186 """ | 168 """ |
187 zip_path = os.path.join(download_folder, 'image.zip') | 169 zip_path = os.path.join(download_folder, 'image.zip') |
188 versioned_url_path = os.path.join(download_folder, 'download_url') | 170 versioned_url_path = os.path.join(download_folder, 'download_url') |
189 found_cached = False | 171 found_cached = False |
190 | 172 |
191 if os.path.exists(versioned_url_path): | 173 if os.path.exists(versioned_url_path): |
192 fh = open(versioned_url_path) | 174 fh = open(versioned_url_path) |
193 version_url = fh.read() | 175 version_url = fh.read() |
194 fh.close() | 176 fh.close() |
195 | 177 |
196 if version_url == zip_url and os.path.exists(os.path.join(download_folder, | 178 if version_url == zip_url and os.path.exists(os.path.join(download_folder, |
197 image_name)): | 179 image_name)): |
198 Info('Using cached %s' % image_name) | 180 cros_lib.Info('Using cached %s' % image_name) |
199 found_cached = True | 181 found_cached = True |
200 | 182 |
201 if not found_cached: | 183 if not found_cached: |
202 Info('Downloading %s' % zip_url) | 184 cros_lib.Info('Downloading %s' % zip_url) |
203 RunCommand(['rm', '-rf', download_folder], print_cmd=False) | 185 cros_lib.RunCommand(['rm', '-rf', download_folder], print_cmd=False) |
204 os.mkdir(download_folder) | 186 os.mkdir(download_folder) |
205 urllib.urlretrieve(zip_url, zip_path) | 187 urllib.urlretrieve(zip_url, zip_path) |
206 | 188 |
207 # Using unzip because python implemented unzip in native python so | 189 # Using unzip because python implemented unzip in native python so |
208 # extraction is really slow. | 190 # extraction is really slow. |
209 Info('Unzipping image %s' % image_name) | 191 cros_lib.Info('Unzipping image %s' % image_name) |
210 RunCommand(['unzip', '-d', download_folder, zip_path], | 192 cros_lib.RunCommand(['unzip', '-d', download_folder, zip_path], |
211 print_cmd=False, error_message='Failed to download %s' % zip_url) | 193 print_cmd=False, error_message='Failed to download %s' % zip_url) |
212 | 194 |
213 ModifyBootDesc(download_folder) | 195 ModifyBootDesc(download_folder) |
214 | 196 |
215 # Put url in version file so we don't have to do this every time. | 197 # Put url in version file so we don't have to do this every time. |
216 fh = open(versioned_url_path, 'w+') | 198 fh = open(versioned_url_path, 'w+') |
217 fh.write(zip_url) | 199 fh.write(zip_url) |
218 fh.close() | 200 fh.close() |
219 | 201 |
220 version = zip_url.split('/')[-2] | 202 version = zip_url.split('/')[-2] |
221 if not _GreaterVersion(version, _NEW_STYLE_VERSION) == version: | 203 if not _GreaterVersion(version, _NEW_STYLE_VERSION) == version: |
222 # If the version isn't ready for new style, touch file to use old style. | 204 # If the version isn't ready for new style, touch file to use old style. |
223 old_style_touch_path = os.path.join(download_folder, '.use_e1000') | 205 old_style_touch_path = os.path.join(download_folder, '.use_e1000') |
224 fh = open(old_style_touch_path, 'w+') | 206 fh = open(old_style_touch_path, 'w+') |
225 fh.close() | 207 fh.close() |
226 | 208 |
227 | 209 |
228 def RunAUTestHarness(board, channel, latest_url_base, zip_server_base, | 210 def RunAUTestHarness(board, channel, zip_server_base, |
229 no_graphics, type, remote, clean, test_results_root): | 211 no_graphics, type, remote, clean, test_results_root): |
230 """Runs the auto update test harness. | 212 """Runs the auto update test harness. |
231 | 213 |
232 The auto update test harness encapsulates testing the auto-update mechanism | 214 The auto update test harness encapsulates testing the auto-update mechanism |
233 for the latest image against the latest official image from the channel. This | 215 for the latest image against the latest official image from the channel. This |
234 also tests images with suite_Smoke (built-in as part of its verification | 216 also tests images with suite_Smoke (built-in as part of its verification |
235 process). | 217 process). |
236 | 218 |
237 Args: | 219 Args: |
238 board: the board for the latest image. | 220 board: the board for the latest image. |
239 channel: the channel to run the au test harness against. | 221 channel: the channel to run the au test harness against. |
240 latest_url_base: base url for getting latest links. | |
241 zip_server_base: base url for zipped images. | 222 zip_server_base: base url for zipped images. |
242 no_graphics: boolean - If True, disable graphics during vm test. | 223 no_graphics: boolean - If True, disable graphics during vm test. |
243 type: which test harness to run. Possible values: real, vm. | 224 type: which test harness to run. Possible values: real, vm. |
244 remote: ip address for real test harness run. | 225 remote: ip address for real test harness run. |
245 clean: Clean the state of test harness before running. | 226 clean: Clean the state of test harness before running. |
246 test_results_root: Root directory to store au_test_harness results. | 227 test_results_root: Root directory to store au_test_harness results. |
247 """ | 228 """ |
248 crosutils_root = os.path.join(os.path.dirname(__file__), '..') | 229 crosutils_root = os.path.join(constants.SOURCE_ROOT, 'src', 'scripts') |
249 download_folder = os.path.abspath('latest_download') | 230 download_folder = os.path.abspath('latest_download') |
250 zip_url = GetLatestZipUrl(board, channel, latest_url_base, zip_server_base) | 231 zip_url = GetLatestZipUrl(board, channel, zip_server_base) |
251 GrabZipAndExtractImage(zip_url, download_folder, _IMAGE_TO_EXTRACT) | 232 GrabZipAndExtractImage(zip_url, download_folder, _IMAGE_TO_EXTRACT) |
252 | 233 |
253 # Tests go here. | 234 # Tests go here. |
254 latest_image = RunCommand(['./get_latest_image.sh', '--board=%s' % board], | 235 return_object = cros_lib.RunCommand( |
255 cwd=crosutils_root, redirect_stdout=True, | 236 ['./get_latest_image.sh', '--board=%s' % board], cwd=crosutils_root, |
256 print_cmd=True).strip() | 237 redirect_stdout=True, print_cmd=True) |
| 238 |
| 239 latest_image = return_object.output.strip() |
257 | 240 |
258 update_engine_path = os.path.join(crosutils_root, '..', 'platform', | 241 update_engine_path = os.path.join(crosutils_root, '..', 'platform', |
259 'update_engine') | 242 'update_engine') |
260 | 243 |
261 cmd = ['bin/cros_au_test_harness', | 244 cmd = ['bin/cros_au_test_harness', |
262 '--base_image=%s' % os.path.join(download_folder, | 245 '--base_image=%s' % os.path.join(download_folder, |
263 _IMAGE_TO_EXTRACT), | 246 _IMAGE_TO_EXTRACT), |
264 '--target_image=%s' % os.path.join(latest_image, | 247 '--target_image=%s' % os.path.join(latest_image, |
265 _IMAGE_TO_EXTRACT), | 248 _IMAGE_TO_EXTRACT), |
266 '--board=%s' % board, | 249 '--board=%s' % board, |
267 '--type=%s' % type, | 250 '--type=%s' % type, |
268 '--remote=%s' % remote, | 251 '--remote=%s' % remote, |
269 '--private_key=%s' % os.path.join(update_engine_path, | 252 '--private_key=%s' % os.path.join(update_engine_path, |
270 'unittest_key.pem'), | 253 'unittest_key.pem'), |
271 '--public_key=%s' % os.path.join(update_engine_path, | 254 '--public_key=%s' % os.path.join(update_engine_path, |
272 'unittest_key.pub.pem'), | 255 'unittest_key.pub.pem'), |
273 ] | 256 ] |
274 if test_results_root: cmd.append('--test_results_root=%s' % test_results_root) | 257 if test_results_root: cmd.append('--test_results_root=%s' % test_results_root) |
275 if no_graphics: cmd.append('--no_graphics') | 258 if no_graphics: cmd.append('--no_graphics') |
276 if clean: cmd.append('--clean') | 259 if clean: cmd.append('--clean') |
277 | 260 |
278 RunCommand(cmd, cwd=crosutils_root) | 261 cros_lib.RunCommand(cmd, cwd=crosutils_root) |
279 | 262 |
280 | 263 |
281 def main(): | 264 def main(): |
282 parser = optparse.OptionParser() | 265 parser = optparse.OptionParser() |
283 parser.add_option('-b', '--board', | 266 parser.add_option('-b', '--board', |
284 help='board for the image to compare against.') | 267 help='board for the image to compare against.') |
285 parser.add_option('-c', '--channel', | 268 parser.add_option('-c', '--channel', |
286 help='channel for the image to compare against.') | 269 help='channel for the image to compare against.') |
287 parser.add_option('--cache', default=False, action='store_true', | 270 parser.add_option('--cache', default=False, action='store_true', |
288 help='Cache payloads') | 271 help='Cache payloads') |
289 parser.add_option('-l', '--latestbase', | |
290 help='Base url for latest links.') | |
291 parser.add_option('-z', '--zipbase', | 272 parser.add_option('-z', '--zipbase', |
292 help='Base url for hosted images.') | 273 help='Base url for hosted images.') |
293 parser.add_option('--no_graphics', action='store_true', default=False, | 274 parser.add_option('--no_graphics', action='store_true', default=False, |
294 help='Disable graphics for the vm test.') | 275 help='Disable graphics for the vm test.') |
295 parser.add_option('--test_results_root', default=None, | 276 parser.add_option('--test_results_root', default=None, |
296 help='Root directory to store test results. Should ' | 277 help='Root directory to store test results. Should ' |
297 'be defined relative to chroot root.') | 278 'be defined relative to chroot root.') |
298 parser.add_option('--type', default='vm', | 279 parser.add_option('--type', default='vm', |
299 help='type of test to run: [vm, real]. Default: vm.') | 280 help='type of test to run: [vm, real]. Default: vm.') |
300 parser.add_option('--remote', default='0.0.0.0', | 281 parser.add_option('--remote', default='0.0.0.0', |
301 help='For real tests, ip address of the target machine.') | 282 help='For real tests, ip address of the target machine.') |
302 | 283 |
303 # Set the usage to include flags. | 284 # Set the usage to include flags. |
304 parser.set_usage(parser.format_help()) | 285 parser.set_usage(parser.format_help()) |
305 (options, args) = parser.parse_args() | 286 (options, args) = parser.parse_args() |
306 | 287 |
307 if args: parser.error('Extra args found %s.' % args) | 288 if args: parser.error('Extra args found %s.' % args) |
308 if not options.board: parser.error('Need board for image to compare against.') | 289 if not options.board: parser.error('Need board for image to compare against.') |
309 if not options.channel: parser.error('Need channel e.g. dev-channel.') | 290 if not options.channel: parser.error('Need channel e.g. dev-channel.') |
310 if not options.zipbase: parser.error('Need zip url base to get images.') | 291 if not options.zipbase: parser.error('Need zip url base to get images.') |
311 | 292 |
312 RunAUTestHarness(options.board, options.channel, options.latestbase, | 293 RunAUTestHarness(options.board, options.channel, options.zipbase, |
313 options.zipbase, options.no_graphics, options.type, | 294 options.no_graphics, options.type, options.remote, |
314 options.remote, not options.cache, | 295 not options.cache, options.test_results_root) |
315 options.test_results_root) | |
316 | 296 |
317 | 297 |
318 if __name__ == '__main__': | 298 if __name__ == '__main__': |
319 main() | 299 main() |
320 | 300 |
OLD | NEW |