| Index: bin/au_test_harness/au_worker.py
|
| diff --git a/bin/au_test_harness/au_worker.py b/bin/au_test_harness/au_worker.py
|
| deleted file mode 100644
|
| index 303c1802084785333d62110261e53a847353099b..0000000000000000000000000000000000000000
|
| --- a/bin/au_test_harness/au_worker.py
|
| +++ /dev/null
|
| @@ -1,272 +0,0 @@
|
| -# Copyright (c) 2011 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.
|
| -
|
| -"""Module that contains the interface for au_test_harness workers.
|
| -
|
| -An au test harnss worker is a class that contains the logic for performing
|
| -and validating updates on a target. This should be subclassed to handle
|
| -various types of target. Types of targets include VM's, real devices, etc.
|
| -"""
|
| -
|
| -import inspect
|
| -import threading
|
| -import os
|
| -import sys
|
| -
|
| -import cros_build_lib as cros_lib
|
| -
|
| -import dev_server_wrapper
|
| -import update_exception
|
| -
|
| -
|
| -class AUWorker(object):
|
| - """Interface for a worker that updates and verifies images."""
|
| - # Mapping between cached payloads to directory locations.
|
| - update_cache = None
|
| -
|
| - # --- INTERFACE ---
|
| -
|
| - def __init__(self, options, test_results_root):
|
| - """Processes options for the specific-type of worker."""
|
| - self.board = options.board
|
| - self.private_key = options.private_key
|
| - self.test_results_root = test_results_root
|
| - self.use_delta_updates = options.delta
|
| - self.verbose = options.verbose
|
| - self.vm_image_path = None
|
| - if options.quick_test:
|
| - self.verify_suite = 'build_RootFilesystemSize'
|
| - else:
|
| - self.verify_suite = 'suite_Smoke'
|
| -
|
| - # Set these up as they are used often.
|
| - self.crosutils = os.path.join(os.path.dirname(__file__), '..', '..')
|
| - self.crosutilsbin = os.path.join(os.path.dirname(__file__), '..')
|
| -
|
| - def CleanUp(self):
|
| - """Called at the end of every test."""
|
| - pass
|
| -
|
| - def UpdateImage(self, image_path, src_image_path='', stateful_change='old',
|
| - proxy_port=None, private_key_path=None):
|
| - """Implementation of an actual update.
|
| -
|
| - See PerformUpdate for description of args. Subclasses must override this
|
| - method with the correct update procedure for the class.
|
| - """
|
| - pass
|
| -
|
| - 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.
|
| -
|
| - Args:
|
| - update_path: Path to the image to update with. This directory should
|
| - contain both update.gz, and stateful.image.gz
|
| - proxy_port: Port to have the client connect to. For use with
|
| - CrosTestProxy.
|
| - """
|
| - pass
|
| -
|
| - def VerifyImage(self, unittest, percent_required_to_pass=100):
|
| - """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.
|
| -
|
| - Args:
|
| - unittest: pointer to a unittest to fail if we cannot verify the image.
|
| - percent_required_to_pass: percentage required to pass. This should be
|
| - fall between 0-100.
|
| -
|
| - Returns:
|
| - Returns the percent that passed.
|
| - """
|
| - pass
|
| -
|
| - # --- INTERFACE TO AU_TEST ---
|
| -
|
| - def PerformUpdate(self, image_path, src_image_path='', stateful_change='old',
|
| - proxy_port=None, private_key_path=None):
|
| - """Performs an update using _UpdateImage and reports any error.
|
| -
|
| - Subclasses should not override this method but override _UpdateImage
|
| - instead.
|
| -
|
| - 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.
|
| - private_key_path: Path to a private key to use with update payload.
|
| - Raises an update_exception.UpdateException if _UpdateImage returns an error.
|
| - """
|
| - try:
|
| - if not self.use_delta_updates: src_image_path = ''
|
| - if private_key_path:
|
| - key_to_use = private_key_path
|
| - else:
|
| - key_to_use = self.private_key
|
| -
|
| - self.UpdateImage(image_path, src_image_path, stateful_change,
|
| - proxy_port, key_to_use)
|
| - except update_exception.UpdateException as err:
|
| - # If the update fails, print it out
|
| - Warning(err.stdout)
|
| - raise
|
| -
|
| - @classmethod
|
| - def SetUpdateCache(cls, update_cache):
|
| - """Sets the global update cache for getting paths to devserver payloads."""
|
| - cls.update_cache = update_cache
|
| -
|
| - # --- METHODS FOR SUB CLASS USE ---
|
| -
|
| - def PrepareRealBase(self, image_path):
|
| - """Prepares a remote device for worker test by updating it to the image."""
|
| - self.UpdateImage(image_path)
|
| -
|
| - def PrepareVMBase(self, image_path):
|
| - """Prepares a VM image for worker test by creating the VM file from the img.
|
| - """
|
| - # VM Constants.
|
| - FULL_VDISK_SIZE = 6072
|
| - FULL_STATEFULFS_SIZE = 3074
|
| - # Needed for VM delta updates. We need to use the qemu image rather
|
| - # than the base image on a first update. By tracking the first_update
|
| - # we can set src_image to the qemu form of the base image when
|
| - # performing generating the delta payload.
|
| - self._first_update = True
|
| - self.vm_image_path = '%s/chromiumos_qemu_image.bin' % os.path.dirname(
|
| - image_path)
|
| - if not os.path.exists(self.vm_image_path):
|
| - cros_lib.Info('Creating %s' % self.vm_image_path)
|
| - cros_lib.RunCommand(['./image_to_vm.sh',
|
| - '--full',
|
| - '--from=%s' % cros_lib.ReinterpretPathForChroot(
|
| - os.path.dirname(image_path)),
|
| - '--vdisk_size=%s' % FULL_VDISK_SIZE,
|
| - '--statefulfs_size=%s' % FULL_STATEFULFS_SIZE,
|
| - '--board=%s' % self.board,
|
| - '--test_image'
|
| - ], enter_chroot=True, cwd=self.crosutils)
|
| -
|
| - cros_lib.Info('Using %s as base' % self.vm_image_path)
|
| - assert os.path.exists(self.vm_image_path)
|
| -
|
| - def GetStatefulChangeFlag(self, stateful_change):
|
| - """Returns the flag to pass to image_to_vm for the stateful change."""
|
| - stateful_change_flag = ''
|
| - if stateful_change:
|
| - stateful_change_flag = '--stateful_update_flag=%s' % stateful_change
|
| -
|
| - return stateful_change_flag
|
| -
|
| - def AppendUpdateFlags(self, cmd, image_path, src_image_path, proxy_port,
|
| - private_key_path):
|
| - """Appends common args to an update cmd defined by an array.
|
| -
|
| - Modifies cmd in places by appending appropriate items given args.
|
| - """
|
| - if proxy_port: cmd.append('--proxy_port=%s' % proxy_port)
|
| -
|
| - # Get pregenerated update if we have one.
|
| - update_id = dev_server_wrapper.GenerateUpdateId(image_path, src_image_path,
|
| - private_key_path)
|
| - cache_path = self.update_cache[update_id]
|
| - if cache_path:
|
| - update_url = dev_server_wrapper.DevServerWrapper.GetDevServerURL(
|
| - proxy_port, cache_path)
|
| - cmd.append('--update_url=%s' % update_url)
|
| - else:
|
| - cmd.append('--image=%s' % image_path)
|
| - if src_image_path: cmd.append('--src_image=%s' % src_image_path)
|
| -
|
| - def RunUpdateCmd(self, cmd, log_directory=None):
|
| - """Runs the given update cmd given verbose options.
|
| -
|
| - Raises an update_exception.UpdateException if the update fails.
|
| - """
|
| - if self.verbose:
|
| - try:
|
| - if log_directory:
|
| - cros_lib.RunCommand(cmd, log_to_file=os.path.join(log_directory,
|
| - 'update.log'))
|
| - else:
|
| - cros_lib.RunCommand(cmd)
|
| - except Exception as e:
|
| - Warning(str(e))
|
| - raise update_exception.UpdateException(1, str(e))
|
| - else:
|
| - (code, stdout, stderr) = cros_lib.RunCommandCaptureOutput(cmd)
|
| - if code != 0:
|
| - Warning(stdout)
|
| - raise update_exception.UpdateException(code, stdout)
|
| -
|
| - def AssertEnoughTestsPassed(self, unittest, output, percent_required_to_pass):
|
| - """Helper function that asserts a sufficient number of tests passed.
|
| -
|
| - Args:
|
| - 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.
|
| - """
|
| - cros_lib.Info('Output from VerifyImage():')
|
| - print >> sys.stderr, output
|
| - sys.stderr.flush()
|
| - percent_passed = self._ParseGenerateTestReportOutput(output)
|
| - cros_lib.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 InitializeResultsDirectory(self):
|
| - """Called by a test to initialize a results directory for this worker."""
|
| - # Use the name of the test.
|
| - test_name = inspect.stack()[1][3]
|
| - self.results_directory = os.path.join(self.test_results_root, test_name)
|
| - self.results_count = 0
|
| -
|
| - def GetNextResultsPath(self, label):
|
| - """Returns a path for the results directory for this label.
|
| -
|
| - Prefixes directory returned for worker with time called i.e. 1_label,
|
| - 2_label, etc. The directory returned is outside the chroot so if passing
|
| - to an script that is called with enther_chroot, make sure to use
|
| - ReinterpretPathForChroot.
|
| - """
|
| - self.results_count += 1
|
| - dir = os.path.join(self.results_directory, '%s_%s' % (self.results_count,
|
| - label))
|
| - if not os.path.exists(dir):
|
| - os.makedirs(dir)
|
| -
|
| - return dir
|
| -
|
| - # --- PRIVATE HELPER FUNCTIONS ---
|
| -
|
| - def _ParseGenerateTestReportOutput(self, output):
|
| - """Returns the percentage of tests that passed based on output."""
|
| - percent_passed = 0
|
| - lines = output.split('\n')
|
| -
|
| - for line in lines:
|
| - if line.startswith("Total PASS:"):
|
| - # FORMAT: ^TOTAL PASS: num_passed/num_total (percent%)$
|
| - percent_passed = line.split()[3].strip('()%')
|
| - cros_lib.Info('Percent of tests passed %s' % percent_passed)
|
| - break
|
| -
|
| - return int(percent_passed)
|
|
|