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

Side by Side Diff: bin/cros_au_test_harness.py

Issue 5573007: Add some desired options to the au test harness. (Closed) Base URL: http://git.chromium.org/git/crosutils.git@master
Patch Set: ws Created 10 years 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | image_to_live.sh » ('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/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 import optparse 7 import optparse
8 import os 8 import os
9 import re 9 import re
10 import sys 10 import sys
(...skipping 12 matching lines...) Expand all
23 _FULL_VDISK_SIZE = 6072 23 _FULL_VDISK_SIZE = 6072
24 _FULL_STATEFULFS_SIZE = 3074 24 _FULL_STATEFULFS_SIZE = 3074
25 _KVM_PID_FILE = '/tmp/harness_pid' 25 _KVM_PID_FILE = '/tmp/harness_pid'
26 _VERIFY_SUITE = 'suite_Smoke' 26 _VERIFY_SUITE = 'suite_Smoke'
27 27
28 # Globals to communicate options to unit tests. 28 # Globals to communicate options to unit tests.
29 global base_image_path 29 global base_image_path
30 global board 30 global board
31 global remote 31 global remote
32 global target_image_path 32 global target_image_path
33 global run_command
33 global vm_graphics_flag 34 global vm_graphics_flag
34 35
35 class UpdateException(Exception): 36 class UpdateException(Exception):
36 """Exception thrown when UpdateImage or UpdateUsingPayload fail""" 37 """Exception thrown when UpdateImage or UpdateUsingPayload fail"""
37 def __init__(self, code, stdout): 38 def __init__(self, code, stdout):
38 self.code = code 39 self.code = code
39 self.stdout = stdout 40 self.stdout = stdout
40 41
41 class AUTest(object): 42 class AUTest(object):
42 """Abstract interface that defines an Auto Update test.""" 43 """Abstract interface that defines an Auto Update test."""
(...skipping 28 matching lines...) Expand all
71 break 72 break
72 73
73 return int(percent_passed) 74 return int(percent_passed)
74 75
75 # TODO(sosa) - Remove try and convert function to DeltaUpdateImage(). 76 # TODO(sosa) - Remove try and convert function to DeltaUpdateImage().
76 def TryDeltaAndFallbackToFull(self, src_image, image, stateful_change='old'): 77 def TryDeltaAndFallbackToFull(self, src_image, image, stateful_change='old'):
77 """Tries the delta update first if set and falls back to full update.""" 78 """Tries the delta update first if set and falls back to full update."""
78 if self.use_delta_updates: 79 if self.use_delta_updates:
79 try: 80 try:
80 self.source_image = src_image 81 self.source_image = src_image
81 self.UpdateImage(image) 82 self._UpdateImageReportError(image)
82 except: 83 except:
83 Warning('Delta update failed, disabling delta updates and retrying.') 84 Warning('Delta update failed, disabling delta updates and retrying.')
84 self.use_delta_updates = False 85 self.use_delta_updates = False
85 self.source_image = '' 86 self.source_image = ''
86 self._UpdateImageReportError(image) 87 self._UpdateImageReportError(image)
87 else: 88 else:
88 self._UpdateImageReportError(image) 89 self._UpdateImageReportError(image)
89 90
90 def _UpdateImageReportError(self, image_path, stateful_change='old'): 91 def _UpdateImageReportError(self, image_path, stateful_change='old'):
91 """Calls UpdateImage and reports any error to the console. 92 """Calls UpdateImage and reports any error to the console.
92 93
93 Still throws the exception. 94 Still throws the exception.
94 """ 95 """
95 try: 96 try:
96 self.UpdateImage(image_path, stateful_change) 97 self.UpdateImage(image_path, stateful_change)
97 except UpdateException as err: 98 except UpdateException as err:
98 # If the update fails, print it out 99 # If the update fails, print it out
99 Warning(err.stdout) 100 Warning(err.stdout)
100 raise 101 raise
101 102
102 def _AttemptUpdateWithPayloadExpectedFailure(self, payload, expected_msg): 103 def _AttemptUpdateWithPayloadExpectedFailure(self, payload, expected_msg):
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 161
161 Args: 162 Args:
162 unittest: Handle to the unittest. 163 unittest: Handle to the unittest.
163 output: stdout from a test run. 164 output: stdout from a test run.
164 percent_required_to_pass: percentage required to pass. This should be 165 percent_required_to_pass: percentage required to pass. This should be
165 fall between 0-100. 166 fall between 0-100.
166 Returns: 167 Returns:
167 percent that passed. 168 percent that passed.
168 """ 169 """
169 Info('Output from VerifyImage():') 170 Info('Output from VerifyImage():')
170 print output 171 print >> sys.stderr, output
172 sys.stderr.flush()
171 percent_passed = self.ParseGenerateTestReportOutput(output) 173 percent_passed = self.ParseGenerateTestReportOutput(output)
172 Info('Percent passed: %d vs. Percent required: %d' % ( 174 Info('Percent passed: %d vs. Percent required: %d' % (
173 percent_passed, percent_required_to_pass)) 175 percent_passed, percent_required_to_pass))
174 unittest.assertTrue(percent_passed >= 176 unittest.assertTrue(percent_passed >=
175 percent_required_to_pass) 177 percent_required_to_pass)
176 return percent_passed 178 return percent_passed
177 179
178 def testFullUpdateKeepStateful(self): 180 def testFullUpdateKeepStateful(self):
179 """Tests if we can update normally. 181 """Tests if we can update normally.
180 182
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 230
229 # Image can be updated at: 231 # Image can be updated at:
230 # ~chrome-eng/chromeos/localmirror/autest-images 232 # ~chrome-eng/chromeos/localmirror/autest-images
231 url = 'http://gsdview.appspot.com/chromeos-localmirror/' \ 233 url = 'http://gsdview.appspot.com/chromeos-localmirror/' \
232 'autest-images/truncated_image.gz' 234 'autest-images/truncated_image.gz'
233 payload = os.path.join(self.download_folder, 'truncated_image.gz') 235 payload = os.path.join(self.download_folder, 'truncated_image.gz')
234 236
235 # Read from the URL and write to the local file 237 # Read from the URL and write to the local file
236 urllib.urlretrieve(url, payload) 238 urllib.urlretrieve(url, payload)
237 239
238 expected_msg='download_hash_data == update_check_response_hash failed' 240 expected_msg = 'download_hash_data == update_check_response_hash failed'
239 self._AttemptUpdateWithPayloadExpectedFailure(payload, expected_msg) 241 self._AttemptUpdateWithPayloadExpectedFailure(payload, expected_msg)
240 242
241 def testCorruptedUpdate(self): 243 def testCorruptedUpdate(self):
242 """Tests what happens if we attempt to update with a corrupted payload.""" 244 """Tests what happens if we attempt to update with a corrupted payload."""
243 # Preload with the version we are trying to test. 245 # Preload with the version we are trying to test.
244 self.PrepareBase(image_path=target_image_path) 246 self.PrepareBase(image_path=target_image_path)
245 247
246 # Image can be updated at: 248 # Image can be updated at:
247 # ~chrome-eng/chromeos/localmirror/autest-images 249 # ~chrome-eng/chromeos/localmirror/autest-images
248 url = 'http://gsdview.appspot.com/chromeos-localmirror/' \ 250 url = 'http://gsdview.appspot.com/chromeos-localmirror/' \
249 'autest-images/corrupted_image.gz' 251 'autest-images/corrupted_image.gz'
250 payload = os.path.join(self.download_folder, 'corrupted.gz') 252 payload = os.path.join(self.download_folder, 'corrupted.gz')
251 253
252 # Read from the URL and write to the local file 254 # Read from the URL and write to the local file
253 urllib.urlretrieve(url, payload) 255 urllib.urlretrieve(url, payload)
254 256
255 # This update is expected to fail... 257 # This update is expected to fail...
256 expected_msg='zlib inflate() error:-3' 258 expected_msg = 'zlib inflate() error:-3'
257 self._AttemptUpdateWithPayloadExpectedFailure(payload, expected_msg) 259 self._AttemptUpdateWithPayloadExpectedFailure(payload, expected_msg)
258 260
259 class RealAUTest(unittest.TestCase, AUTest): 261 class RealAUTest(unittest.TestCase, AUTest):
260 """Test harness for updating real images.""" 262 """Test harness for updating real images."""
261 263
262 def setUp(self): 264 def setUp(self):
263 AUTest.setUp(self) 265 AUTest.setUp(self)
264 266
265 def PrepareBase(self, image_path): 267 def PrepareBase(self, image_path):
266 """Auto-update to base image to prepare for test.""" 268 """Auto-update to base image to prepare for test."""
267 self._UpdateImageReportError(image_path) 269 self._UpdateImageReportError(image_path)
268 270
269 def UpdateImage(self, image_path, stateful_change='old'): 271 def UpdateImage(self, image_path, stateful_change='old'):
270 """Updates a remote image using image_to_live.sh.""" 272 """Updates a remote image using image_to_live.sh."""
271 stateful_change_flag = self.GetStatefulChangeFlag(stateful_change) 273 stateful_change_flag = self.GetStatefulChangeFlag(stateful_change)
272 274
273 (code, stdout, stderr) = RunCommandCaptureOutput([ 275 (code, stdout, stderr) = run_command([
274 '%s/image_to_live.sh' % self.crosutils, 276 '%s/image_to_live.sh' % self.crosutils,
275 '--image=%s' % image_path, 277 '--image=%s' % image_path,
276 '--remote=%s' % remote, 278 '--remote=%s' % remote,
277 stateful_change_flag, 279 stateful_change_flag,
278 '--verify', 280 '--verify',
279 '--src_image=%s' % self.source_image 281 '--src_image=%s' % self.source_image
280 ]) 282 ])
281 283
282 if code != 0: 284 if code != 0:
283 raise UpdateException(code, stdout) 285 raise UpdateException(code, stdout)
284 286
285 def UpdateUsingPayload(self, update_path, stateful_change='old'): 287 def UpdateUsingPayload(self, update_path, stateful_change='old'):
286 """Updates a remote image using image_to_live.sh.""" 288 """Updates a remote image using image_to_live.sh."""
287 stateful_change_flag = self.GetStatefulChangeFlag(stateful_change) 289 stateful_change_flag = self.GetStatefulChangeFlag(stateful_change)
288 290
289 (code, stdout, stderr) = RunCommandCaptureOutput([ 291 (code, stdout, stderr) = run_command([
290 '%s/image_to_live.sh' % self.crosutils, 292 '%s/image_to_live.sh' % self.crosutils,
291 '--payload=%s' % update_path, 293 '--payload=%s' % update_path,
292 '--remote=%s' % remote, 294 '--remote=%s' % remote,
293 stateful_change_flag, 295 stateful_change_flag,
294 '--verify', 296 '--verify',
295 ]) 297 ])
296 298
297 if code != 0: 299 if code != 0:
298 raise UpdateException(code, stdout) 300 raise UpdateException(code, stdout)
299 301
(...skipping 24 matching lines...) Expand all
324 326
325 def setUp(self): 327 def setUp(self):
326 """Unit test overriden method. Is called before every test.""" 328 """Unit test overriden method. Is called before every test."""
327 AUTest.setUp(self) 329 AUTest.setUp(self)
328 self._KillExistingVM(_KVM_PID_FILE) 330 self._KillExistingVM(_KVM_PID_FILE)
329 331
330 def PrepareBase(self, image_path): 332 def PrepareBase(self, image_path):
331 """Creates an update-able VM based on base image.""" 333 """Creates an update-able VM based on base image."""
332 self.vm_image_path = '%s/chromiumos_qemu_image.bin' % os.path.dirname( 334 self.vm_image_path = '%s/chromiumos_qemu_image.bin' % os.path.dirname(
333 image_path) 335 image_path)
334 336
335 Info('Creating: %s' % self.vm_image_path) 337 Info('Creating: %s' % self.vm_image_path)
336 338
337 if not os.path.exists(self.vm_image_path): 339 if not os.path.exists(self.vm_image_path):
338 Info('Qemu image %s not found, creating one.' % self.vm_image_path) 340 Info('Qemu image %s not found, creating one.' % self.vm_image_path)
339 RunCommand(['%s/image_to_vm.sh' % self.crosutils, 341 RunCommand(['%s/image_to_vm.sh' % self.crosutils,
340 '--full', 342 '--full',
341 '--from=%s' % ReinterpretPathForChroot( 343 '--from=%s' % ReinterpretPathForChroot(
342 os.path.dirname(image_path)), 344 os.path.dirname(image_path)),
343 '--vdisk_size=%s' % _FULL_VDISK_SIZE, 345 '--vdisk_size=%s' % _FULL_VDISK_SIZE,
344 '--statefulfs_size=%s' % _FULL_STATEFULFS_SIZE, 346 '--statefulfs_size=%s' % _FULL_STATEFULFS_SIZE,
345 '--board=%s' % board, 347 '--board=%s' % board,
346 '--test_image'], enter_chroot=True) 348 '--test_image'], enter_chroot=True)
347 else: 349 else:
348 Info('Using existing VM image %s' % self.vm_image_path) 350 Info('Using existing VM image %s' % self.vm_image_path)
349 351
350 352
351 Info('Testing for %s' % self.vm_image_path) 353 Info('Testing for %s' % self.vm_image_path)
352 354
353 self.assertTrue(os.path.exists(self.vm_image_path)) 355 self.assertTrue(os.path.exists(self.vm_image_path))
354 356
355 def UpdateImage(self, image_path, stateful_change='old'): 357 def UpdateImage(self, image_path, stateful_change='old'):
356 """Updates VM image with image_path.""" 358 """Updates VM image with image_path."""
357 stateful_change_flag = self.GetStatefulChangeFlag(stateful_change) 359 stateful_change_flag = self.GetStatefulChangeFlag(stateful_change)
358 if self.source_image == base_image_path: 360 if self.source_image == base_image_path:
359 self.source_image = self.vm_image_path 361 self.source_image = self.vm_image_path
360 362
361 (code, stdout, stderr) = RunCommandCaptureOutput([ 363 (code, stdout, stderr) = run_command([
362 '%s/cros_run_vm_update' % self.crosutilsbin, 364 '%s/cros_run_vm_update' % self.crosutilsbin,
363 '--update_image_path=%s' % image_path, 365 '--update_image_path=%s' % image_path,
364 '--vm_image_path=%s' % self.vm_image_path, 366 '--vm_image_path=%s' % self.vm_image_path,
365 '--snapshot', 367 '--snapshot',
366 vm_graphics_flag, 368 vm_graphics_flag,
367 '--persist', 369 '--persist',
368 '--kvm_pid=%s' % _KVM_PID_FILE, 370 '--kvm_pid=%s' % _KVM_PID_FILE,
369 stateful_change_flag, 371 stateful_change_flag,
370 '--src_image=%s' % self.source_image, 372 '--src_image=%s' % self.source_image,
371 ]) 373 ])
372 374
373 if code != 0: 375 if code != 0:
374 raise UpdateException(code, stdout) 376 raise UpdateException(code, stdout)
375 377
376 def UpdateUsingPayload(self, update_path, stateful_change='old'): 378 def UpdateUsingPayload(self, update_path, stateful_change='old'):
377 """Updates a remote image using image_to_live.sh.""" 379 """Updates a remote image using image_to_live.sh."""
378 stateful_change_flag = self.GetStatefulChangeFlag(stateful_change) 380 stateful_change_flag = self.GetStatefulChangeFlag(stateful_change)
379 if self.source_image == base_image_path: 381 if self.source_image == base_image_path:
380 self.source_image = self.vm_image_path 382 self.source_image = self.vm_image_path
381 383
382 (code, stdout, stderr) = RunCommandCaptureOutput([ 384 (code, stdout, stderr) = run_command([
383 '%s/cros_run_vm_update' % self.crosutilsbin, 385 '%s/cros_run_vm_update' % self.crosutilsbin,
384 '--payload=%s' % update_path, 386 '--payload=%s' % update_path,
385 '--vm_image_path=%s' % self.vm_image_path, 387 '--vm_image_path=%s' % self.vm_image_path,
386 '--snapshot', 388 '--snapshot',
387 vm_graphics_flag, 389 vm_graphics_flag,
388 '--persist', 390 '--persist',
389 '--kvm_pid=%s' % _KVM_PID_FILE, 391 '--kvm_pid=%s' % _KVM_PID_FILE,
390 stateful_change_flag, 392 stateful_change_flag,
391 '--src_image=%s' % self.source_image, 393 '--src_image=%s' % self.source_image,
392 ]) 394 ])
(...skipping 19 matching lines...) Expand all
412 414
413 output = RunCommand(commandWithArgs, error_ok=True, enter_chroot=False, 415 output = RunCommand(commandWithArgs, error_ok=True, enter_chroot=False,
414 redirect_stdout=True) 416 redirect_stdout=True)
415 return self.CommonVerifyImage(self, output, percent_required_to_pass) 417 return self.CommonVerifyImage(self, output, percent_required_to_pass)
416 418
417 419
418 if __name__ == '__main__': 420 if __name__ == '__main__':
419 parser = optparse.OptionParser() 421 parser = optparse.OptionParser()
420 parser.add_option('-b', '--base_image', 422 parser.add_option('-b', '--base_image',
421 help='path to the base image.') 423 help='path to the base image.')
422 parser.add_option('-t', '--target_image',
423 help='path to the target image.')
424 parser.add_option('-r', '--board', 424 parser.add_option('-r', '--board',
425 help='board for the images.') 425 help='board for the images.')
426 parser.add_option('-p', '--type', default='vm',
427 help='type of test to run: [vm, real]. Default: vm.')
428 parser.add_option('-m', '--remote',
429 help='Remote address for real test.')
430 parser.add_option('--no_graphics', action='store_true',
431 help='Disable graphics for the vm test.')
432 parser.add_option('--no_delta', action='store_false', default=True, 426 parser.add_option('--no_delta', action='store_false', default=True,
433 dest='delta', 427 dest='delta',
434 help='Disable using delta updates.') 428 help='Disable using delta updates.')
429 parser.add_option('--no_graphics', action='store_true',
sosa 2010/12/03 22:33:28 I just sorted this by long name
430 help='Disable graphics for the vm test.')
431 parser.add_option('-m', '--remote',
432 help='Remote address for real test.')
435 parser.add_option('-q', '--quick_test', default=False, action='store_true', 433 parser.add_option('-q', '--quick_test', default=False, action='store_true',
436 help='Use a basic test to verify image.') 434 help='Use a basic test to verify image.')
435 parser.add_option('-t', '--target_image',
436 help='path to the target image.')
437 parser.add_option('--test_prefix', default='test',
438 help='Only runs tests with specific prefix i.e. '
439 'testFullUpdateWipeStateful.')
440 parser.add_option('-p', '--type', default='vm',
441 help='type of test to run: [vm, real]. Default: vm.')
442 parser.add_option('--verbose', default=False, action='store_true',
443 help='Print out rather than capture output as much as '
444 'possible.')
437 # Set the usage to include flags. 445 # Set the usage to include flags.
438 parser.set_usage(parser.format_help()) 446 parser.set_usage(parser.format_help())
439 # Parse existing sys.argv so we can pass rest to unittest.main. 447 # Parse existing sys.argv so we can pass rest to unittest.main.
440 (options, sys.argv) = parser.parse_args(sys.argv) 448 (options, sys.argv) = parser.parse_args(sys.argv)
441 449
442 base_image_path = options.base_image 450 base_image_path = options.base_image
443 target_image_path = options.target_image 451 target_image_path = options.target_image
444 board = options.board 452 board = options.board
453 run_command = RunCommandCaptureOutput
454 if options.verbose: run_command = RunCommand
dgarrett 2010/12/06 18:35:23 This isn't quite what I thought you meant when we
445 455
446 if not base_image_path: 456 if not base_image_path:
447 parser.error('Need path to base image for vm.') 457 parser.error('Need path to base image for vm.')
448 elif not os.path.exists(base_image_path): 458 elif not os.path.exists(base_image_path):
449 Die('%s does not exist' % base_image_path) 459 Die('%s does not exist' % base_image_path)
450 460
451 if not target_image_path: 461 if not target_image_path:
452 parser.error('Need path to target image to update with.') 462 parser.error('Need path to target image to update with.')
453 elif not os.path.exists(target_image_path): 463 elif not os.path.exists(target_image_path):
454 Die('%s does not exist' % target_image_path) 464 Die('%s does not exist' % target_image_path)
455 465
456 if not board: 466 if not board:
457 parser.error('Need board to convert base image to vm.') 467 parser.error('Need board to convert base image to vm.')
458 468
459 # Communicate flags to tests. 469 # Communicate flags to tests.
460 vm_graphics_flag = '' 470 vm_graphics_flag = ''
461 if options.no_graphics: vm_graphics_flag = '--no_graphics' 471 if options.no_graphics: vm_graphics_flag = '--no_graphics'
462 if options.quick_test: _VERIFY_SUITE = 'build_RootFilesystemSize' 472 if options.quick_test: _VERIFY_SUITE = 'build_RootFilesystemSize'
463 AUTest.use_delta_updates = options.delta 473 AUTest.use_delta_updates = options.delta
464 474
465 # Only run the test harness we care about. 475 # Only run the test harness we care about.
466 if options.type == 'vm': 476 test_loader = unittest.TestLoader()
467 suite = unittest.TestLoader().loadTestsFromTestCase(VirtualAUTest) 477 test_loader.testMethodPrefix = options.test_prefix
sosa 2010/12/03 22:33:28 Cleaned this up to make it easier to read and put
468 test_result = unittest.TextTestRunner(verbosity=2).run(suite)
469 elif options.type == 'real':
470 if not options.remote:
471 parser.error('Real tests require a remote test machine.')
472 else:
473 remote = options.remote
474 478
475 suite = unittest.TestLoader().loadTestsFromTestCase(RealAUTest) 479 if options.type == 'vm': test_class = VirtualAUTest
476 test_result = unittest.TextTestRunner(verbosity=2).run(suite) 480 elif options.type == 'real': test_class = RealAUTest
477 else: 481 else: parser.error('Could not parse harness type %s.' % options.type)
478 parser.error('Could not parse harness type %s.' % options.type) 482
483 test_suite = test_loader.loadTestsFromTestCase(test_class)
484 test_result = unittest.TextTestRunner(verbosity=2).run(test_suite)
479 485
480 if not test_result.wasSuccessful(): 486 if not test_result.wasSuccessful():
481 Die('Test harness was not successful') 487 Die('Test harness was not successful')
OLDNEW
« no previous file with comments | « no previous file | image_to_live.sh » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698