| Index: bin/cros_au_test_harness.py
|
| diff --git a/bin/cros_au_test_harness.py b/bin/cros_au_test_harness.py
|
| index 5a0182c4815812a99af29a0655e34456917b87f8..5d5b221760c0dab765dd10645ca088f2daf24681 100755
|
| --- a/bin/cros_au_test_harness.py
|
| +++ b/bin/cros_au_test_harness.py
|
| @@ -1,6 +1,6 @@
|
| #!/usr/bin/python
|
|
|
| -# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
|
| +# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
|
| # Use of this source code is governed by a BSD-style license that can be
|
| # found in the LICENSE file.
|
|
|
| @@ -23,16 +23,29 @@ from cros_build_lib import Warning
|
|
|
| import cros_test_proxy
|
|
|
| +# VM Constants.
|
| +_FULL_VDISK_SIZE = 6072
|
| +_FULL_STATEFULFS_SIZE = 3074
|
| +_KVM_PID_FILE = '/tmp/harness_pid'
|
| +_VERIFY_SUITE = 'suite_Smoke'
|
| +
|
| +# Globals to communicate options to unit tests.
|
| +global base_image_path
|
| +global board
|
| +global remote
|
| +global target_image_path
|
| +global vm_graphics_flag
|
|
|
| class UpdateException(Exception):
|
| - """Exception thrown when _UpdateImage or _UpdateUsingPayload fail"""
|
| + """Exception thrown when UpdateImage or UpdateUsingPayload fail"""
|
| def __init__(self, code, stdout):
|
| self.code = code
|
| self.stdout = stdout
|
|
|
| -
|
| class AUTest(object):
|
| """Abstract interface that defines an Auto Update test."""
|
| + source_image = ''
|
| + use_delta_updates = False
|
| verbose = False
|
|
|
| def setUp(self):
|
| @@ -44,8 +57,6 @@ class AUTest(object):
|
| if not os.path.exists(self.download_folder):
|
| os.makedirs(self.download_folder)
|
|
|
| - # -------- Helper functions ---------
|
| -
|
| def GetStatefulChangeFlag(self, stateful_change):
|
| """Returns the flag to pass to image_to_vm for the stateful change."""
|
| stateful_change_flag = ''
|
| @@ -54,7 +65,7 @@ class AUTest(object):
|
|
|
| return stateful_change_flag
|
|
|
| - def _ParseGenerateTestReportOutput(self, output):
|
| + def ParseGenerateTestReportOutput(self, output):
|
| """Returns the percentage of tests that passed based on output."""
|
| percent_passed = 0
|
| lines = output.split('\n')
|
| @@ -68,60 +79,38 @@ class AUTest(object):
|
|
|
| return int(percent_passed)
|
|
|
| - def AssertEnoughTestsPassed(self, unittest, output, percent_required_to_pass):
|
| - """Helper function that asserts a sufficient number of tests passed.
|
| -
|
| - Args:
|
| - unittest: Handle to the unittest.
|
| - output: stdout from a test run.
|
| - percent_required_to_pass: percentage required to pass. This should be
|
| - fall between 0-100.
|
| - Returns:
|
| - percent that passed.
|
| - """
|
| - Info('Output from VerifyImage():')
|
| - print >> sys.stderr, output
|
| - sys.stderr.flush()
|
| - percent_passed = self._ParseGenerateTestReportOutput(output)
|
| - Info('Percent passed: %d vs. Percent required: %d' % (
|
| - percent_passed, percent_required_to_pass))
|
| - unittest.assertTrue(percent_passed >= percent_required_to_pass)
|
| - return percent_passed
|
| -
|
| - def PerformUpdate(self, image_path, src_image_path='', stateful_change='old',
|
| - proxy_port=None):
|
| - """Performs an update using _UpdateImage and reports any error.
|
| + # TODO(sosa) - Remove try and convert function to DeltaUpdateImage().
|
| + def TryDeltaAndFallbackToFull(self, src_image, image, stateful_change='old'):
|
| + """Tries the delta update first if set and falls back to full update."""
|
| + if self.use_delta_updates:
|
| + try:
|
| + self.source_image = src_image
|
| + self._UpdateImageReportError(image, stateful_change)
|
| + except:
|
| + Warning('Delta update failed, disabling delta updates and retrying.')
|
| + self.use_delta_updates = False
|
| + self.source_image = ''
|
| + self._UpdateImageReportError(image, stateful_change)
|
| + else:
|
| + self._UpdateImageReportError(image, stateful_change)
|
|
|
| - Subclasses should not override this method but override _UpdateImage
|
| - instead.
|
| + def _UpdateImageReportError(self, image_path, stateful_change='old',
|
| + proxy_port=None):
|
| + """Calls UpdateImage and reports any error to the console.
|
|
|
| - Args:
|
| - image_path: Path to the image to update with. This image must be a test
|
| - image.
|
| - src_image_path: Optional. If set, perform a delta update using the
|
| - image specified by the path as the source image.
|
| - stateful_change: How to modify the stateful partition. Values are:
|
| - 'old': Don't modify stateful partition. Just update normally.
|
| - 'clean': Uses clobber-state to wipe the stateful partition with the
|
| - exception of code needed for ssh.
|
| - proxy_port: Port to have the client connect to. For use with
|
| - CrosTestProxy.
|
| - Raises an UpdateException if _UpdateImage returns an error.
|
| + Still throws the exception.
|
| """
|
| try:
|
| - if not self.use_delta_updates:
|
| - src_image_path = ''
|
| -
|
| - self._UpdateImage(image_path, src_image_path, stateful_change, proxy_port)
|
| + self.UpdateImage(image_path, stateful_change, proxy_port)
|
| except UpdateException as err:
|
| # If the update fails, print it out
|
| Warning(err.stdout)
|
| raise
|
|
|
| - def AttemptUpdateWithPayloadExpectedFailure(self, payload, expected_msg):
|
| + def _AttemptUpdateWithPayloadExpectedFailure(self, payload, expected_msg):
|
| """Attempt a payload update, expect it to fail with expected log"""
|
| try:
|
| - self._UpdateUsingPayload(payload)
|
| + self.UpdateUsingPayload(payload)
|
| except UpdateException as err:
|
| # Will raise ValueError if expected is not found.
|
| if re.search(re.escape(expected_msg), err.stdout, re.MULTILINE):
|
| @@ -131,10 +120,10 @@ class AUTest(object):
|
| Warning(err.stdout)
|
| self.fail('We managed to update when failure was expected')
|
|
|
| - def AttemptUpdateWithFilter(self, filter):
|
| + def _AttemptUpdateWithFilter(self, filter):
|
| """Update through a proxy, with a specified filter, and expect success."""
|
|
|
| - self.PrepareBase(self.target_image_path)
|
| + self.PrepareBase(target_image_path)
|
|
|
| # The devserver runs at port 8080 by default. We assume that here, and
|
| # start our proxy at 8081. We then tell our update tools to have the
|
| @@ -148,58 +137,34 @@ class AUTest(object):
|
|
|
| # This update is expected to fail...
|
| try:
|
| - self.PerformUpdate(self.target_image_path, proxy_port=proxy_port)
|
| + self._UpdateImageReportError(target_image_path, proxy_port=proxy_port)
|
| finally:
|
| proxy.shutdown()
|
|
|
| - # -------- Functions that subclasses should override ---------
|
| -
|
| - @classmethod
|
| - def ProcessOptions(cls, parser, options):
|
| - """Processes options.
|
| -
|
| - Static method that should be called from main. Subclasses should also
|
| - call their parent method if they override it.
|
| - """
|
| - cls.verbose = options.verbose
|
| - cls.base_image_path = options.base_image
|
| - cls.target_image_path = options.target_image
|
| - cls.use_delta_updates = options.delta
|
| - if options.quick_test:
|
| - cls.verify_suite = 'build_RootFilesystemSize'
|
| - else:
|
| - cls.verify_suite = 'suite_Smoke'
|
| -
|
| - # Sanity checks.
|
| - if not cls.base_image_path:
|
| - parser.error('Need path to base image for vm.')
|
| - elif not os.path.exists(cls.base_image_path):
|
| - Die('%s does not exist' % cls.base_image_path)
|
| -
|
| - if not cls.target_image_path:
|
| - parser.error('Need path to target image to update with.')
|
| - elif not os.path.exists(cls.target_image_path):
|
| - Die('%s does not exist' % cls.target_image_path)
|
| -
|
| def PrepareBase(self, image_path):
|
| """Prepares target with base_image_path."""
|
| pass
|
|
|
| - def _UpdateImage(self, image_path, src_image_path='', stateful_change='old',
|
| - proxy_port=None):
|
| - """Implementation of an actual update.
|
| + def UpdateImage(self, image_path, stateful_change='old', proxy_port=None):
|
| + """Updates target with the image given by the image_path.
|
|
|
| - See PerformUpdate for description of args. Subclasses must override this
|
| - method with the correct update procedure for the class.
|
| + Args:
|
| + image_path: Path to the image to update with. This image must be a test
|
| + image.
|
| + stateful_change: How to modify the stateful partition. Values are:
|
| + 'old': Don't modify stateful partition. Just update normally.
|
| + 'clean': Uses clobber-state to wipe the stateful partition with the
|
| + exception of code needed for ssh.
|
| + proxy_port: Port to have the client connect to. For use with
|
| + CrosTestProxy.
|
| """
|
| pass
|
|
|
| - def _UpdateUsingPayload(self, update_path, stateful_change='old',
|
| + def UpdateUsingPayload(self,
|
| + update_path,
|
| + stateful_change='old',
|
| proxy_port=None):
|
| - """Updates target with the pre-generated update stored in update_path.
|
| -
|
| - Subclasses must override this method with the correct update procedure for
|
| - the class.
|
| + """Updates target with the pre-generated update stored in update_path
|
|
|
| Args:
|
| update_path: Path to the image to update with. This directory should
|
| @@ -212,8 +177,7 @@ class AUTest(object):
|
| def VerifyImage(self, percent_required_to_pass):
|
| """Verifies the image with tests.
|
|
|
| - Verifies that the test images passes the percent required. Subclasses must
|
| - override this method with the correct update procedure for the class.
|
| + Verifies that the test images passes the percent required.
|
|
|
| Args:
|
| percent_required_to_pass: percentage required to pass. This should be
|
| @@ -224,7 +188,29 @@ class AUTest(object):
|
| """
|
| pass
|
|
|
| - # -------- Tests ---------
|
| + def CommonVerifyImage(self, unittest, output, percent_required_to_pass):
|
| + """Helper function for VerifyImage that returns percent of tests passed.
|
| +
|
| + Takes output from a test suite, verifies the number of tests passed is
|
| + sufficient and outputs info.
|
| +
|
| + Args:
|
| + unittest: Handle to the unittest.
|
| + output: stdout from a test run.
|
| + percent_required_to_pass: percentage required to pass. This should be
|
| + fall between 0-100.
|
| + Returns:
|
| + percent that passed.
|
| + """
|
| + Info('Output from VerifyImage():')
|
| + print >> sys.stderr, output
|
| + sys.stderr.flush()
|
| + percent_passed = self.ParseGenerateTestReportOutput(output)
|
| + Info('Percent passed: %d vs. Percent required: %d' % (
|
| + percent_passed, percent_required_to_pass))
|
| + unittest.assertTrue(percent_passed >=
|
| + percent_required_to_pass)
|
| + return percent_passed
|
|
|
| def testFullUpdateKeepStateful(self):
|
| """Tests if we can update normally.
|
| @@ -234,19 +220,19 @@ class AUTest(object):
|
| """
|
| # Just make sure some tests pass on original image. Some old images
|
| # don't pass many tests.
|
| - self.PrepareBase(self.base_image_path)
|
| + self.PrepareBase(base_image_path)
|
| # TODO(sosa): move to 100% once we start testing using the autotest paired
|
| # with the dev channel.
|
| percent_passed = self.VerifyImage(10)
|
|
|
| # Update to - all tests should pass on new image.
|
| Info('Updating from base image on vm to target image.')
|
| - self.PerformUpdate(self.base_image_path, self.target_image_path)
|
| + self.TryDeltaAndFallbackToFull(base_image_path, target_image_path)
|
| self.VerifyImage(100)
|
|
|
| # Update from - same percentage should pass that originally passed.
|
| Info('Updating from updated image on vm back to base image.')
|
| - self.PerformUpdate(self.target_image_path, self.base_image_path)
|
| + self.TryDeltaAndFallbackToFull(target_image_path, base_image_path)
|
| self.VerifyImage(percent_passed)
|
|
|
| def testFullUpdateWipeStateful(self):
|
| @@ -257,25 +243,25 @@ class AUTest(object):
|
| """
|
| # Just make sure some tests pass on original image. Some old images
|
| # don't pass many tests.
|
| - self.PrepareBase(self.base_image_path)
|
| + self.PrepareBase(base_image_path)
|
| # TODO(sosa): move to 100% once we start testing using the autotest paired
|
| # with the dev channel.
|
| percent_passed = self.VerifyImage(10)
|
|
|
| # Update to - all tests should pass on new image.
|
| Info('Updating from base image on vm to target image and wiping stateful.')
|
| - self.PerformUpdate(self.base_image_path, self.target_image_path, 'clean')
|
| + self.TryDeltaAndFallbackToFull(base_image_path, target_image_path, 'clean')
|
| self.VerifyImage(100)
|
|
|
| # Update from - same percentage should pass that originally passed.
|
| Info('Updating from updated image back to base image and wiping stateful.')
|
| - self.PerformUpdate(self.target_image_path, self.base_image_path, 'clean')
|
| + self.TryDeltaAndFallbackToFull(target_image_path, base_image_path, 'clean')
|
| self.VerifyImage(percent_passed)
|
|
|
| def testPartialUpdate(self):
|
| """Tests what happens if we attempt to update with a truncated payload."""
|
| # Preload with the version we are trying to test.
|
| - self.PrepareBase(self.target_image_path)
|
| + self.PrepareBase(target_image_path)
|
|
|
| # Image can be updated at:
|
| # ~chrome-eng/chromeos/localmirror/autest-images
|
| @@ -287,12 +273,12 @@ class AUTest(object):
|
| urllib.urlretrieve(url, payload)
|
|
|
| expected_msg = 'download_hash_data == update_check_response_hash failed'
|
| - self.AttemptUpdateWithPayloadExpectedFailure(payload, expected_msg)
|
| + self._AttemptUpdateWithPayloadExpectedFailure(payload, expected_msg)
|
|
|
| def testCorruptedUpdate(self):
|
| """Tests what happens if we attempt to update with a corrupted payload."""
|
| # Preload with the version we are trying to test.
|
| - self.PrepareBase(self.target_image_path)
|
| + self.PrepareBase(target_image_path)
|
|
|
| # Image can be updated at:
|
| # ~chrome-eng/chromeos/localmirror/autest-images
|
| @@ -305,7 +291,7 @@ class AUTest(object):
|
|
|
| # This update is expected to fail...
|
| expected_msg = 'zlib inflate() error:-3'
|
| - self.AttemptUpdateWithPayloadExpectedFailure(payload, expected_msg)
|
| + self._AttemptUpdateWithPayloadExpectedFailure(payload, expected_msg)
|
|
|
| def testInterruptedUpdate(self):
|
| """Tests what happens if we interrupt payload delivery 3 times."""
|
| @@ -339,7 +325,7 @@ class AUTest(object):
|
| self.data_size += len(data)
|
| return data
|
|
|
| - self.AttemptUpdateWithFilter(InterruptionFilter())
|
| + self._AttemptUpdateWithFilter(InterruptionFilter())
|
|
|
| def testDelayedUpdate(self):
|
| """Tests what happens if some data is delayed during update delivery"""
|
| @@ -369,7 +355,7 @@ class AUTest(object):
|
| self.data_size += len(data)
|
| return data
|
|
|
| - self.AttemptUpdateWithFilter(DelayedFilter())
|
| + self._AttemptUpdateWithFilter(DelayedFilter())
|
|
|
| def SimpleTest(self):
|
| """A simple update that updates the target image to itself.
|
| @@ -377,8 +363,8 @@ class AUTest(object):
|
| We explicitly don't use test prefix so that isn't run by default. Can be
|
| run using test_prefix option.
|
| """
|
| - self.PrepareBase(self.target_image_path)
|
| - self._UpdateImage(self.target_image_path)
|
| + self.PrepareBase(target_image_path)
|
| + self.UpdateImage(target_image_path)
|
| self.VerifyImage(100)
|
|
|
|
|
| @@ -388,29 +374,19 @@ class RealAUTest(unittest.TestCase, AUTest):
|
| def setUp(self):
|
| AUTest.setUp(self)
|
|
|
| - @classmethod
|
| - def ProcessOptions(cls, parser, options):
|
| - """Processes non-vm-specific options."""
|
| - AUTest.ProcessOptions(parser, options)
|
| - cls.remote = options.remote
|
| -
|
| - if not cls.remote:
|
| - parser.error('We require a remote address for real tests.')
|
| -
|
| def PrepareBase(self, image_path):
|
| """Auto-update to base image to prepare for test."""
|
| - self.PerformUpdate(image_path)
|
| + self._UpdateImageReportError(image_path)
|
|
|
| - def _UpdateImage(self, image_path, src_image_path='', stateful_change='old',
|
| - proxy_port=None):
|
| + def UpdateImage(self, image_path, stateful_change='old', proxy_port=None):
|
| """Updates a remote image using image_to_live.sh."""
|
| stateful_change_flag = self.GetStatefulChangeFlag(stateful_change)
|
| cmd = ['%s/image_to_live.sh' % self.crosutils,
|
| '--image=%s' % image_path,
|
| - '--remote=%s' % self.remote,
|
| + '--remote=%s' % remote,
|
| stateful_change_flag,
|
| '--verify',
|
| - '--src_image=%s' % src_image_path
|
| + '--src_image=%s' % self.source_image
|
| ]
|
|
|
| if proxy_port:
|
| @@ -426,13 +402,15 @@ class RealAUTest(unittest.TestCase, AUTest):
|
| if code != 0:
|
| raise UpdateException(code, stdout)
|
|
|
| - def _UpdateUsingPayload(self, update_path, stateful_change='old',
|
| + def UpdateUsingPayload(self,
|
| + update_path,
|
| + stateful_change='old',
|
| proxy_port=None):
|
| """Updates a remote image using image_to_live.sh."""
|
| stateful_change_flag = self.GetStatefulChangeFlag(stateful_change)
|
| cmd = ['%s/image_to_live.sh' % self.crosutils,
|
| '--payload=%s' % update_path,
|
| - '--remote=%s' % self.remote,
|
| + '--remote=%s' % remote,
|
| stateful_change_flag,
|
| '--verify',
|
| ]
|
| @@ -454,21 +432,16 @@ class RealAUTest(unittest.TestCase, AUTest):
|
| """Verifies an image using run_remote_tests.sh with verification suite."""
|
| output = RunCommand([
|
| '%s/run_remote_tests.sh' % self.crosutils,
|
| - '--remote=%s' % self.remote,
|
| - self.verify_suite,
|
| + '--remote=%s' % remote,
|
| + _VERIFY_SUITE,
|
| ], error_ok=True, enter_chroot=False, redirect_stdout=True)
|
| - return self.AssertEnoughTestsPassed(self, output, percent_required_to_pass)
|
| + return self.CommonVerifyImage(self, output, percent_required_to_pass)
|
|
|
|
|
| class VirtualAUTest(unittest.TestCase, AUTest):
|
| """Test harness for updating virtual machines."""
|
| vm_image_path = None
|
|
|
| - # VM Constants.
|
| - _FULL_VDISK_SIZE = 6072
|
| - _FULL_STATEFULFS_SIZE = 3074
|
| - _KVM_PID_FILE = '/tmp/harness_pid'
|
| -
|
| def _KillExistingVM(self, pid_file):
|
| if os.path.exists(pid_file):
|
| Warning('Existing %s found. Deleting and killing process' %
|
| @@ -481,20 +454,7 @@ class VirtualAUTest(unittest.TestCase, AUTest):
|
| def setUp(self):
|
| """Unit test overriden method. Is called before every test."""
|
| AUTest.setUp(self)
|
| - self._KillExistingVM(self._KVM_PID_FILE)
|
| -
|
| - @classmethod
|
| - def ProcessOptions(cls, parser, options):
|
| - """Processes vm-specific options."""
|
| - AUTest.ProcessOptions(parser, options)
|
| - cls.board = options.board
|
| -
|
| - # Communicate flags to tests.
|
| - cls.graphics_flag = ''
|
| - if options.no_graphics: cls.graphics_flag = '--no_graphics'
|
| -
|
| - if not cls.board:
|
| - parser.error('Need board to convert base image to vm.')
|
| + self._KillExistingVM(_KVM_PID_FILE)
|
|
|
| def PrepareBase(self, image_path):
|
| """Creates an update-able VM based on base image."""
|
| @@ -509,32 +469,33 @@ class VirtualAUTest(unittest.TestCase, AUTest):
|
| '--full',
|
| '--from=%s' % ReinterpretPathForChroot(
|
| os.path.dirname(image_path)),
|
| - '--vdisk_size=%s' % self._FULL_VDISK_SIZE,
|
| - '--statefulfs_size=%s' % self._FULL_STATEFULFS_SIZE,
|
| - '--board=%s' % self.board,
|
| + '--vdisk_size=%s' % _FULL_VDISK_SIZE,
|
| + '--statefulfs_size=%s' % _FULL_STATEFULFS_SIZE,
|
| + '--board=%s' % board,
|
| '--test_image'], enter_chroot=True)
|
| else:
|
| Info('Using existing VM image %s' % self.vm_image_path)
|
|
|
| +
|
| Info('Testing for %s' % self.vm_image_path)
|
| +
|
| self.assertTrue(os.path.exists(self.vm_image_path))
|
|
|
| - def _UpdateImage(self, image_path, src_image_path='', stateful_change='old',
|
| - proxy_port=None):
|
| + def UpdateImage(self, image_path, stateful_change='old', proxy_port=None):
|
| """Updates VM image with image_path."""
|
| stateful_change_flag = self.GetStatefulChangeFlag(stateful_change)
|
| - if src_image_path == self.base_image_path:
|
| - src_image_path = self.vm_image_path
|
| + if self.source_image == base_image_path:
|
| + self.source_image = self.vm_image_path
|
|
|
| cmd = ['%s/cros_run_vm_update' % self.crosutilsbin,
|
| '--update_image_path=%s' % image_path,
|
| '--vm_image_path=%s' % self.vm_image_path,
|
| '--snapshot',
|
| - self.graphics_flag,
|
| + vm_graphics_flag,
|
| '--persist',
|
| - '--kvm_pid=%s' % self._KVM_PID_FILE,
|
| + '--kvm_pid=%s' % _KVM_PID_FILE,
|
| stateful_change_flag,
|
| - '--src_image=%s' % src_image_path,
|
| + '--src_image=%s' % self.source_image,
|
| ]
|
|
|
| if proxy_port:
|
| @@ -550,18 +511,24 @@ class VirtualAUTest(unittest.TestCase, AUTest):
|
| if code != 0:
|
| raise UpdateException(code, stdout)
|
|
|
| - def _UpdateUsingPayload(self, update_path, stateful_change='old',
|
| + def UpdateUsingPayload(self,
|
| + update_path,
|
| + stateful_change='old',
|
| proxy_port=None):
|
| """Updates a remote image using image_to_live.sh."""
|
| stateful_change_flag = self.GetStatefulChangeFlag(stateful_change)
|
| + if self.source_image == base_image_path:
|
| + self.source_image = self.vm_image_path
|
| +
|
| cmd = ['%s/cros_run_vm_update' % self.crosutilsbin,
|
| '--payload=%s' % update_path,
|
| '--vm_image_path=%s' % self.vm_image_path,
|
| '--snapshot',
|
| - self.graphics_flag,
|
| + vm_graphics_flag,
|
| '--persist',
|
| - '--kvm_pid=%s' % self._KVM_PID_FILE,
|
| + '--kvm_pid=%s' % _KVM_PID_FILE,
|
| stateful_change_flag,
|
| + '--src_image=%s' % self.source_image,
|
| ]
|
|
|
| if proxy_port:
|
| @@ -586,19 +553,19 @@ class VirtualAUTest(unittest.TestCase, AUTest):
|
| '--image_path=%s' % self.vm_image_path,
|
| '--snapshot',
|
| '--persist',
|
| - '--kvm_pid=%s' % self._KVM_PID_FILE,
|
| - self.verify_suite,
|
| + '--kvm_pid=%s' % _KVM_PID_FILE,
|
| + _VERIFY_SUITE,
|
| ]
|
|
|
| - if self.graphics_flag:
|
| - commandWithArgs.append(self.graphics_flag)
|
| + if vm_graphics_flag:
|
| + commandWithArgs.append(vm_graphics_flag)
|
|
|
| output = RunCommand(commandWithArgs, error_ok=True, enter_chroot=False,
|
| redirect_stdout=True)
|
| - return self.AssertEnoughTestsPassed(self, output, percent_required_to_pass)
|
| + return self.CommonVerifyImage(self, output, percent_required_to_pass)
|
|
|
|
|
| -def main():
|
| +if __name__ == '__main__':
|
| parser = optparse.OptionParser()
|
| parser.add_option('-b', '--base_image',
|
| help='path to the base image.')
|
| @@ -623,25 +590,47 @@ def main():
|
| parser.add_option('--verbose', default=False, action='store_true',
|
| help='Print out rather than capture output as much as '
|
| 'possible.')
|
| - (options, leftover_args) = parser.parse_args()
|
| -
|
| - if leftover_args:
|
| - parser.error('Found extra options we do not support: %s' % leftover_args)
|
| + # Set the usage to include flags.
|
| + parser.set_usage(parser.format_help())
|
| + # Parse existing sys.argv so we can pass rest to unittest.main.
|
| + (options, sys.argv) = parser.parse_args(sys.argv)
|
| +
|
| + AUTest.verbose = options.verbose
|
| + base_image_path = options.base_image
|
| + target_image_path = options.target_image
|
| + board = options.board
|
| +
|
| + if not base_image_path:
|
| + parser.error('Need path to base image for vm.')
|
| + elif not os.path.exists(base_image_path):
|
| + Die('%s does not exist' % base_image_path)
|
| +
|
| + if not target_image_path:
|
| + parser.error('Need path to target image to update with.')
|
| + elif not os.path.exists(target_image_path):
|
| + Die('%s does not exist' % target_image_path)
|
| +
|
| + if not board:
|
| + parser.error('Need board to convert base image to vm.')
|
| +
|
| + # Communicate flags to tests.
|
| + vm_graphics_flag = ''
|
| + if options.no_graphics: vm_graphics_flag = '--no_graphics'
|
| + if options.quick_test: _VERIFY_SUITE = 'build_RootFilesystemSize'
|
| + AUTest.use_delta_updates = options.delta
|
| +
|
| + # Only run the test harness we care about.
|
| + test_loader = unittest.TestLoader()
|
| + test_loader.testMethodPrefix = options.test_prefix
|
|
|
| if options.type == 'vm': test_class = VirtualAUTest
|
| elif options.type == 'real': test_class = RealAUTest
|
| else: parser.error('Could not parse harness type %s.' % options.type)
|
|
|
| - test_class.ProcessOptions(parser, options)
|
| + remote = options.remote
|
|
|
| - test_loader = unittest.TestLoader()
|
| - test_loader.testMethodPrefix = options.test_prefix
|
| test_suite = test_loader.loadTestsFromTestCase(test_class)
|
| test_result = unittest.TextTestRunner(verbosity=2).run(test_suite)
|
|
|
| if not test_result.wasSuccessful():
|
| Die('Test harness was not successful')
|
| -
|
| -
|
| -if __name__ == '__main__':
|
| - main()
|
|
|