Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 | 2 |
| 3 # Copyright (c) 2011 The Chromium OS Authors. All rights reserved. | 3 # Copyright (c) 2011 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 """This module runs a suite of Auto Update tests. | 7 """This module runs a suite of Auto Update tests. |
| 8 | 8 |
| 9 The tests can be run on either a virtual machine or actual device depending | 9 The tests can be run on either a virtual machine or actual device depending |
| 10 on parameters given. Specific tests can be run by invoking --test_prefix. | 10 on parameters given. Specific tests can be run by invoking --test_prefix. |
| 11 Verbose is useful for many of the tests if you want to see individual commands | 11 Verbose is useful for many of the tests if you want to see individual commands |
| 12 being run during the update process. | 12 being run during the update process. |
| 13 """ | 13 """ |
| 14 | 14 |
| 15 import optparse | 15 import optparse |
| 16 import os | 16 import os |
| 17 import re | 17 import re |
| 18 import sys | 18 import sys |
| 19 import thread | 19 import threading |
| 20 import time | 20 import time |
| 21 import unittest | 21 import unittest |
| 22 import urllib | 22 import urllib |
| 23 | 23 |
| 24 sys.path.append(os.path.join(os.path.dirname(__file__), '../lib')) | 24 sys.path.append(os.path.join(os.path.dirname(__file__), '../lib')) |
| 25 from cros_build_lib import Die | 25 from cros_build_lib import Die |
| 26 from cros_build_lib import Info | 26 from cros_build_lib import Info |
| 27 from cros_build_lib import ReinterpretPathForChroot | 27 from cros_build_lib import ReinterpretPathForChroot |
| 28 from cros_build_lib import RunCommand | 28 from cros_build_lib import RunCommand |
| 29 from cros_build_lib import RunCommandCaptureOutput | 29 from cros_build_lib import RunCommandCaptureOutput |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 127 raise | 127 raise |
| 128 | 128 |
| 129 def AttemptUpdateWithPayloadExpectedFailure(self, payload, expected_msg): | 129 def AttemptUpdateWithPayloadExpectedFailure(self, payload, expected_msg): |
| 130 """Attempt a payload update, expect it to fail with expected log""" | 130 """Attempt a payload update, expect it to fail with expected log""" |
| 131 try: | 131 try: |
| 132 self._UpdateUsingPayload(payload) | 132 self._UpdateUsingPayload(payload) |
| 133 except UpdateException as err: | 133 except UpdateException as err: |
| 134 # Will raise ValueError if expected is not found. | 134 # Will raise ValueError if expected is not found. |
| 135 if re.search(re.escape(expected_msg), err.stdout, re.MULTILINE): | 135 if re.search(re.escape(expected_msg), err.stdout, re.MULTILINE): |
| 136 return | 136 return |
| 137 except Exception as err: | |
|
dgarrett
2011/01/20 03:34:27
After reading this again, the new exception handle
sosa
2011/01/20 03:59:49
Done.
| |
| 138 Warning("Didn't find '%s' in:" % expected_msg) | |
| 139 Warning(err.stdout) | |
| 137 | 140 |
| 138 Warning("Didn't find '%s' in:" % expected_msg) | |
| 139 Warning(err.stdout) | |
| 140 self.fail('We managed to update when failure was expected') | 141 self.fail('We managed to update when failure was expected') |
| 141 | 142 |
| 142 def AttemptUpdateWithFilter(self, filter, proxy_port=8081): | 143 def AttemptUpdateWithFilter(self, filter, proxy_port=8081): |
| 143 """Update through a proxy, with a specified filter, and expect success.""" | 144 """Update through a proxy, with a specified filter, and expect success.""" |
| 144 | 145 |
| 145 self.PrepareBase(self.target_image_path) | 146 self.PrepareBase(self.target_image_path) |
| 146 | 147 |
| 147 # The devserver runs at port 8080 by default. We assume that here, and | 148 # The devserver runs at port 8080 by default. We assume that here, and |
| 148 # start our proxy at a different. We then tell our update tools to | 149 # start our proxy at a different. We then tell our update tools to |
| 149 # have the client connect to our proxy_port instead of 8080. | 150 # have the client connect to our proxy_port instead of 8080. |
| 150 proxy = cros_test_proxy.CrosTestProxy(port_in=proxy_port, | 151 proxy = cros_test_proxy.CrosTestProxy(port_in=proxy_port, |
| 151 address_out='127.0.0.1', | 152 address_out='127.0.0.1', |
| 152 port_out=8080, | 153 port_out=8080, |
| 153 filter=filter) | 154 filter=filter) |
| 154 proxy.serve_forever_in_thread() | 155 proxy.serve_forever_in_thread() |
| 155 | 156 |
| 156 # This update is expected to fail... | 157 # This update is expected to fail... |
| 157 try: | 158 try: |
| 158 self.PerformUpdate(self.target_image_path, self.base_image_path, | 159 self.PerformUpdate(self.target_image_path, self.target_image_path, |
| 159 proxy_port=proxy_port) | 160 proxy_port=proxy_port) |
| 160 finally: | 161 finally: |
| 161 proxy.shutdown() | 162 proxy.shutdown() |
| 162 | 163 |
| 163 # -------- Functions that subclasses should override --------- | 164 # -------- Functions that subclasses should override --------- |
| 164 | 165 |
| 165 @classmethod | 166 @classmethod |
| 166 def ProcessOptions(cls, parser, options): | 167 def ProcessOptions(cls, parser, options): |
| 167 """Processes options. | 168 """Processes options. |
| 168 | 169 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 241 rather than wiping it. | 242 rather than wiping it. |
| 242 """ | 243 """ |
| 243 # Just make sure some tests pass on original image. Some old images | 244 # Just make sure some tests pass on original image. Some old images |
| 244 # don't pass many tests. | 245 # don't pass many tests. |
| 245 self.PrepareBase(self.base_image_path) | 246 self.PrepareBase(self.base_image_path) |
| 246 # TODO(sosa): move to 100% once we start testing using the autotest paired | 247 # TODO(sosa): move to 100% once we start testing using the autotest paired |
| 247 # with the dev channel. | 248 # with the dev channel. |
| 248 percent_passed = self.VerifyImage(10) | 249 percent_passed = self.VerifyImage(10) |
| 249 | 250 |
| 250 # Update to - all tests should pass on new image. | 251 # Update to - all tests should pass on new image. |
| 251 Info('Updating from base image on vm to target image.') | |
| 252 self.PerformUpdate(self.target_image_path, self.base_image_path) | 252 self.PerformUpdate(self.target_image_path, self.base_image_path) |
| 253 self.VerifyImage(100) | 253 self.VerifyImage(100) |
| 254 | 254 |
| 255 # Update from - same percentage should pass that originally passed. | 255 # Update from - same percentage should pass that originally passed. |
| 256 Info('Updating from updated image on vm back to base image.') | |
| 257 self.PerformUpdate(self.base_image_path, self.target_image_path) | 256 self.PerformUpdate(self.base_image_path, self.target_image_path) |
| 258 self.VerifyImage(percent_passed) | 257 self.VerifyImage(percent_passed) |
| 259 | 258 |
| 260 def testUpdateWipeStateful(self): | 259 def testUpdateWipeStateful(self): |
| 261 """Tests if we can update after cleaning the stateful partition. | 260 """Tests if we can update after cleaning the stateful partition. |
| 262 | 261 |
| 263 This test checks that we can update successfully after wiping the | 262 This test checks that we can update successfully after wiping the |
| 264 stateful partition. | 263 stateful partition. |
| 265 """ | 264 """ |
| 266 # Just make sure some tests pass on original image. Some old images | 265 # Just make sure some tests pass on original image. Some old images |
| 267 # don't pass many tests. | 266 # don't pass many tests. |
| 268 self.PrepareBase(self.base_image_path) | 267 self.PrepareBase(self.base_image_path) |
| 269 # TODO(sosa): move to 100% once we start testing using the autotest paired | 268 # TODO(sosa): move to 100% once we start testing using the autotest paired |
| 270 # with the dev channel. | 269 # with the dev channel. |
| 271 percent_passed = self.VerifyImage(10) | 270 percent_passed = self.VerifyImage(10) |
| 272 | 271 |
| 273 # Update to - all tests should pass on new image. | 272 # Update to - all tests should pass on new image. |
| 274 Info('Updating from base image on vm to target image and wiping stateful.') | |
| 275 self.PerformUpdate(self.target_image_path, self.base_image_path, 'clean') | 273 self.PerformUpdate(self.target_image_path, self.base_image_path, 'clean') |
| 276 self.VerifyImage(100) | 274 self.VerifyImage(100) |
| 277 | 275 |
| 278 # Update from - same percentage should pass that originally passed. | 276 # Update from - same percentage should pass that originally passed. |
| 279 Info('Updating from updated image back to base image and wiping stateful.') | |
| 280 self.PerformUpdate(self.base_image_path, self.target_image_path, 'clean') | 277 self.PerformUpdate(self.base_image_path, self.target_image_path, 'clean') |
| 281 self.VerifyImage(percent_passed) | 278 self.VerifyImage(percent_passed) |
| 282 | 279 |
| 283 # TODO(sosa): Get test to work with verbose. | 280 # TODO(sosa): Get test to work with verbose. |
| 284 def NotestPartialUpdate(self): | 281 def NotestPartialUpdate(self): |
| 285 """Tests what happens if we attempt to update with a truncated payload.""" | 282 """Tests what happens if we attempt to update with a truncated payload.""" |
| 286 # Preload with the version we are trying to test. | 283 # Preload with the version we are trying to test. |
| 287 self.PrepareBase(self.target_image_path) | 284 self.PrepareBase(self.target_image_path) |
| 288 | 285 |
| 289 # Image can be updated at: | 286 # Image can be updated at: |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 501 | 498 |
| 502 # Communicate flags to tests. | 499 # Communicate flags to tests. |
| 503 cls.graphics_flag = '' | 500 cls.graphics_flag = '' |
| 504 if options.no_graphics: cls.graphics_flag = '--no_graphics' | 501 if options.no_graphics: cls.graphics_flag = '--no_graphics' |
| 505 | 502 |
| 506 if not cls.board: | 503 if not cls.board: |
| 507 parser.error('Need board to convert base image to vm.') | 504 parser.error('Need board to convert base image to vm.') |
| 508 | 505 |
| 509 def PrepareBase(self, image_path): | 506 def PrepareBase(self, image_path): |
| 510 """Creates an update-able VM based on base image.""" | 507 """Creates an update-able VM based on base image.""" |
| 508 self._first_update = True | |
|
dgarrett
2011/01/20 03:34:27
A comment explaining the purpose of _first_image w
sosa
2011/01/20 03:59:49
Done.
| |
| 511 self.vm_image_path = '%s/chromiumos_qemu_image.bin' % os.path.dirname( | 509 self.vm_image_path = '%s/chromiumos_qemu_image.bin' % os.path.dirname( |
| 512 image_path) | 510 image_path) |
| 511 if not os.path.exists(self.vm_image_path): | |
| 512 Info('Creating %s' % vm_image_path) | |
| 513 RunCommand(['%s/image_to_vm.sh' % self.crosutils, | |
| 514 '--full', | |
| 515 '--from=%s' % ReinterpretPathForChroot( | |
| 516 os.path.dirname(image_path)), | |
| 517 '--vdisk_size=%s' % self._FULL_VDISK_SIZE, | |
| 518 '--statefulfs_size=%s' % self._FULL_STATEFULFS_SIZE, | |
| 519 '--board=%s' % self.board, | |
| 520 '--test_image'], enter_chroot=True) | |
|
dgarrett
2011/01/20 03:34:27
arguments should be indented to match the open [.
sosa
2011/01/20 03:59:49
Done.
| |
| 513 | 521 |
| 514 Info('Creating: %s' % self.vm_image_path) | 522 Info('Using %s as base' % self.vm_image_path) |
| 515 | |
| 516 if not os.path.exists(self.vm_image_path): | |
| 517 Info('Qemu image %s not found, creating one.' % self.vm_image_path) | |
| 518 RunCommand(['%s/image_to_vm.sh' % self.crosutils, | |
| 519 '--full', | |
| 520 '--from=%s' % ReinterpretPathForChroot( | |
| 521 os.path.dirname(image_path)), | |
| 522 '--vdisk_size=%s' % self._FULL_VDISK_SIZE, | |
| 523 '--statefulfs_size=%s' % self._FULL_STATEFULFS_SIZE, | |
| 524 '--board=%s' % self.board, | |
| 525 '--test_image'], enter_chroot=True) | |
| 526 else: | |
| 527 Info('Using existing VM image %s' % self.vm_image_path) | |
| 528 | |
| 529 Info('Testing for %s' % self.vm_image_path) | |
| 530 self.assertTrue(os.path.exists(self.vm_image_path)) | 523 self.assertTrue(os.path.exists(self.vm_image_path)) |
| 531 | 524 |
| 532 def _UpdateImage(self, image_path, src_image_path='', stateful_change='old', | 525 def _UpdateImage(self, image_path, src_image_path='', stateful_change='old', |
| 533 proxy_port=None): | 526 proxy_port=None): |
| 534 """Updates VM image with image_path.""" | 527 """Updates VM image with image_path.""" |
| 535 stateful_change_flag = self.GetStatefulChangeFlag(stateful_change) | 528 stateful_change_flag = self.GetStatefulChangeFlag(stateful_change) |
| 536 if src_image_path == self.base_image_path: | 529 if self._first_update: |
| 537 src_image_path = self.vm_image_path | 530 src_image_path = self.vm_image_path |
| 531 self._first_update = False | |
| 538 | 532 |
| 539 cmd = ['%s/cros_run_vm_update' % self.crosutilsbin, | 533 cmd = ['%s/cros_run_vm_update' % self.crosutilsbin, |
| 540 '--update_image_path=%s' % image_path, | 534 '--update_image_path=%s' % image_path, |
| 541 '--vm_image_path=%s' % self.vm_image_path, | 535 '--vm_image_path=%s' % self.vm_image_path, |
| 542 '--snapshot', | 536 '--snapshot', |
| 543 self.graphics_flag, | 537 self.graphics_flag, |
| 544 '--persist', | 538 '--persist', |
| 545 '--kvm_pid=%s' % self._KVM_PID_FILE, | 539 '--kvm_pid=%s' % self._KVM_PID_FILE, |
| 546 stateful_change_flag, | 540 stateful_change_flag, |
| 547 '--src_image=%s' % src_image_path, | 541 '--src_image=%s' % src_image_path, |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 601 ] | 595 ] |
| 602 | 596 |
| 603 if self.graphics_flag: | 597 if self.graphics_flag: |
| 604 commandWithArgs.append(self.graphics_flag) | 598 commandWithArgs.append(self.graphics_flag) |
| 605 | 599 |
| 606 output = RunCommand(commandWithArgs, error_ok=True, enter_chroot=False, | 600 output = RunCommand(commandWithArgs, error_ok=True, enter_chroot=False, |
| 607 redirect_stdout=True) | 601 redirect_stdout=True) |
| 608 return self.AssertEnoughTestsPassed(self, output, percent_required_to_pass) | 602 return self.AssertEnoughTestsPassed(self, output, percent_required_to_pass) |
| 609 | 603 |
| 610 | 604 |
| 605 class GenerateVirtualAUDeltasTest(VirtualAUTest): | |
| 606 """Class the overrides VirtualAUTest and stores deltas we will generate.""" | |
| 607 delta_list = {} | |
| 608 | |
| 609 def setUp(self): | |
| 610 AUTest.setUp(self) | |
| 611 | |
| 612 def _UpdateImage(self, image_path, src_image_path='', stateful_change='old', | |
| 613 proxy_port=None): | |
| 614 if self._first_update: | |
| 615 src_image_path = self.vm_image_path | |
| 616 self._first_update = False | |
| 617 | |
| 618 image_path = ReinterpretPathForChroot(image_path) | |
| 619 if src_image_path: | |
| 620 src_image_path = ReinterpretPathForChroot(src_image_path) | |
| 621 if not self.delta_list.has_key(image_path): | |
| 622 self.delta_list[image_path] = set([src_image_path]) | |
| 623 else: | |
| 624 self.delta_list[image_path].add(src_image_path) | |
| 625 | |
| 626 def AttemptUpdateWithPayloadExpectedFailure(self, payload, expected_msg): | |
| 627 pass | |
| 628 | |
| 629 def VerifyImage(self, percent_required_to_pass): | |
| 630 pass | |
| 631 | |
| 632 | |
| 633 class ParallelJob(threading.Thread): | |
| 634 """Small wrapper for threading.Thread that releases a semaphore on exit.""" | |
| 635 def __init__(self, semaphore, target, args): | |
| 636 threading.Thread.__init__(self, target=target, args=args) | |
| 637 self._target = target | |
| 638 self._args = args | |
| 639 self._semaphore = semaphore | |
| 640 self._output = None | |
| 641 self._completed = False | |
| 642 | |
| 643 def run(self): | |
| 644 try: | |
| 645 threading.Thread.run(self) | |
| 646 finally: | |
| 647 self._Cleanup() | |
| 648 self._completed = True | |
| 649 | |
| 650 def GetOutput(self): | |
| 651 assert self._completed, 'GetOutput called before thread was run.' | |
| 652 return self._output | |
| 653 | |
| 654 def _Cleanup(self): | |
| 655 self._semaphore.release() | |
| 656 | |
| 657 def __str__(self): | |
| 658 return '%s(%s)' % (self._target, self._args) | |
| 659 | |
| 660 | |
| 661 def _RunParallelJobs(number_of_sumultaneous_jobs, jobs, jobs_args): | |
| 662 """Runs set number of specified jobs in parallel. | |
| 663 | |
| 664 Args: | |
| 665 number_of_simultaneous_jobs: Max number of threads to be run in parallel. | |
| 666 jobs: Array of methods to run. | |
| 667 jobs_args: Array of args associated with method calls. | |
| 668 Returns: | |
| 669 Returns an array of results corresponding to each thread. | |
| 670 """ | |
| 671 def _TwoTupleize(x, y): | |
| 672 return (x, y) | |
| 673 | |
| 674 threads = [] | |
| 675 job_pool_semaphore = threading.Semaphore(number_of_sumultaneous_jobs) | |
| 676 assert len(jobs) == len(jobs_args), 'Length of args array is wrong.' | |
| 677 | |
| 678 # Create the parallel jobs. | |
| 679 for job, args in map(_TwoTupleize, jobs, jobs_args): | |
| 680 thread = ParallelJob(job_pool_semaphore, target=job, args=args) | |
| 681 threads.append(thread) | |
| 682 | |
| 683 # We use a semaphore to ensure we don't run more jobs that required. | |
| 684 # After each thread finishes, it releases (increments semaphore). | |
| 685 # Acquire blocks of num jobs reached and continues when a thread finishes. | |
| 686 for next_thread in threads: | |
| 687 job_pool_semaphore.acquire(blocking=True) | |
| 688 Info('Starting %s' % next_thread) | |
| 689 next_thread.start() | |
| 690 | |
| 691 # Wait on the rest of the threads to finish. | |
| 692 for thread in threads: | |
| 693 thread.join() | |
| 694 | |
| 695 return [thread.GetOutput() for thread in threads] | |
| 696 | |
| 697 | |
| 698 def _PregenerateUpdates(parser, options): | |
| 699 """Determines all deltas that will be generated and generates them. | |
| 700 | |
| 701 This method effectively pre-generates the dev server cache for all tests. | |
| 702 | |
| 703 Args: | |
| 704 parser: parser from main. | |
| 705 options: options from parsed parser. | |
| 706 Returns: | |
| 707 Array of output from generating updates. | |
| 708 """ | |
| 709 def _GenerateVMUpdate(target, src): | |
| 710 """Generates an update using the devserver.""" | |
| 711 RunCommand(['./start_devserver', | |
| 712 '--pregenerate_update', | |
| 713 '--exit', | |
| 714 '--image=%s' % src, | |
| 715 '--src_image=%s' % target, | |
| 716 ], redirect_stderr=True) | |
| 717 | |
| 718 # Get the list of deltas by mocking out update method in test class. | |
| 719 GenerateVirtualAUDeltasTest.ProcessOptions(parser, options) | |
| 720 test_loader = unittest.TestLoader() | |
| 721 test_loader.testMethodPrefix = options.test_prefix | |
| 722 test_suite = test_loader.loadTestsFromTestCase(GenerateVirtualAUDeltasTest) | |
| 723 test_result = unittest.TextTestRunner(verbosity=0).run(test_suite) | |
| 724 | |
| 725 Info('The following delta updates are required.') | |
| 726 jobs = [] | |
| 727 args = [] | |
| 728 for target, srcs in GenerateVirtualAUDeltasTest.delta_list.items(): | |
| 729 for src in srcs: | |
| 730 print >> sys.stderr, '%s -> %s' % (src, target) | |
| 731 jobs.append(_GenerateVMUpdate) | |
| 732 args.append((target, src)) | |
| 733 | |
| 734 results = _RunParallelJobs(options.jobs, jobs, args) | |
| 735 return results | |
| 736 | |
| 737 | |
| 611 def main(): | 738 def main(): |
| 612 parser = optparse.OptionParser() | 739 parser = optparse.OptionParser() |
| 613 parser.add_option('-b', '--base_image', | 740 parser.add_option('-b', '--base_image', |
| 614 help='path to the base image.') | 741 help='path to the base image.') |
| 615 parser.add_option('-r', '--board', | 742 parser.add_option('-r', '--board', |
| 616 help='board for the images.') | 743 help='board for the images.') |
| 617 parser.add_option('--no_delta', action='store_false', default=True, | 744 parser.add_option('--no_delta', action='store_false', default=True, |
| 618 dest='delta', | 745 dest='delta', |
| 619 help='Disable using delta updates.') | 746 help='Disable using delta updates.') |
| 620 parser.add_option('--no_graphics', action='store_true', | 747 parser.add_option('--no_graphics', action='store_true', |
| 621 help='Disable graphics for the vm test.') | 748 help='Disable graphics for the vm test.') |
| 749 parser.add_option('-j', '--jobs', default=8, type=int, | |
| 750 help='Number of simultaneous jobs') | |
| 751 parser.add_option('-q', '--quick_test', default=False, action='store_true', | |
| 752 help='Use a basic test to verify image.') | |
| 622 parser.add_option('-m', '--remote', | 753 parser.add_option('-m', '--remote', |
| 623 help='Remote address for real test.') | 754 help='Remote address for real test.') |
| 624 parser.add_option('-q', '--quick_test', default=False, action='store_true', | |
| 625 help='Use a basic test to verify image.') | |
| 626 parser.add_option('-t', '--target_image', | 755 parser.add_option('-t', '--target_image', |
| 627 help='path to the target image.') | 756 help='path to the target image.') |
| 628 parser.add_option('--test_prefix', default='test', | 757 parser.add_option('--test_prefix', default='test', |
| 629 help='Only runs tests with specific prefix i.e. ' | 758 help='Only runs tests with specific prefix i.e. ' |
| 630 'testFullUpdateWipeStateful.') | 759 'testFullUpdateWipeStateful.') |
| 631 parser.add_option('-p', '--type', default='vm', | 760 parser.add_option('-p', '--type', default='vm', |
| 632 help='type of test to run: [vm, real]. Default: vm.') | 761 help='type of test to run: [vm, real]. Default: vm.') |
| 633 parser.add_option('--verbose', default=True, action='store_true', | 762 parser.add_option('--verbose', default=True, action='store_true', |
| 634 help='Print out rather than capture output as much as ' | 763 help='Print out rather than capture output as much as ' |
| 635 'possible.') | 764 'possible.') |
| 636 (options, leftover_args) = parser.parse_args() | 765 (options, leftover_args) = parser.parse_args() |
| 637 | 766 |
| 638 if leftover_args: | 767 if leftover_args: |
| 639 parser.error('Found extra options we do not support: %s' % leftover_args) | 768 parser.error('Found extra options we do not support: %s' % leftover_args) |
| 640 | 769 |
| 641 if options.type == 'vm': test_class = VirtualAUTest | 770 if options.type == 'vm': test_class = VirtualAUTest |
| 642 elif options.type == 'real': test_class = RealAUTest | 771 elif options.type == 'real': test_class = RealAUTest |
| 643 else: parser.error('Could not parse harness type %s.' % options.type) | 772 else: parser.error('Could not parse harness type %s.' % options.type) |
| 644 | 773 |
| 774 # TODO(sosa): Caching doesn't work with non-delta updates. Also, it doesn't | |
| 775 # really make sense on non-vm images (yet). | |
| 776 if options.delta and options.type == 'vm': | |
| 777 _PregenerateUpdates(parser, options) | |
| 778 | |
| 779 # Run the test suite. | |
| 645 test_class.ProcessOptions(parser, options) | 780 test_class.ProcessOptions(parser, options) |
| 646 | |
| 647 test_loader = unittest.TestLoader() | 781 test_loader = unittest.TestLoader() |
| 648 test_loader.testMethodPrefix = options.test_prefix | 782 test_loader.testMethodPrefix = options.test_prefix |
| 649 test_suite = test_loader.loadTestsFromTestCase(test_class) | 783 test_suite = test_loader.loadTestsFromTestCase(test_class) |
| 650 test_result = unittest.TextTestRunner(verbosity=2).run(test_suite) | 784 test_result = unittest.TextTestRunner(verbosity=2).run(test_suite) |
| 651 | |
| 652 if not test_result.wasSuccessful(): | 785 if not test_result.wasSuccessful(): |
| 653 Die('Test harness was not successful') | 786 Die('Test harness was not successful.') |
| 654 | 787 |
| 655 | 788 |
| 656 if __name__ == '__main__': | 789 if __name__ == '__main__': |
| 657 main() | 790 main() |
| OLD | NEW |