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

Unified Diff: bin/cros_au_test_harness.py

Issue 6482017: Update test harness to take in optional public and private keys to sign payloads. (Closed) Base URL: http://git.chromium.org/git/crosutils.git@master
Patch Set: Fix a bug I found Created 9 years, 10 months 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | bin/cros_run_vm_update » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: bin/cros_au_test_harness.py
diff --git a/bin/cros_au_test_harness.py b/bin/cros_au_test_harness.py
index 67c0485ba08ea58e74a81a726eed19ff22ac7639..06e08f49b39be889eaddd43ee1253321f3a75945 100755
--- a/bin/cros_au_test_harness.py
+++ b/bin/cros_au_test_harness.py
@@ -15,8 +15,10 @@
import optparse
import os
import re
+import shutil
import subprocess
import sys
+import tempfile
import threading
import time
import unittest
@@ -53,11 +55,74 @@ class AUTest(object):
self.crosutils = os.path.join(os.path.dirname(__file__), '..')
self.crosutilsbin = os.path.join(os.path.dirname(__file__))
self.download_folder = os.path.join(self.crosutils, 'latest_download')
+ self.vm_image_path = None
if not os.path.exists(self.download_folder):
os.makedirs(self.download_folder)
# -------- Helper functions ---------
+ def _PrepareRealBase(self, image_path):
+ self.PerformUpdate(image_path)
+
+ def _PrepareVMBase(self, image_path):
+ # 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):
+ Info('Creating %s' % self.vm_image_path)
+ RunCommand(['%s/image_to_vm.sh' % self.crosutils,
+ '--full',
+ '--from=%s' % 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)
+
+ Info('Using %s as base' % self.vm_image_path)
+ self.assertTrue(os.path.exists(self.vm_image_path))
+
+ 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 = _GenerateUpdateId(target=image_path, src=src_image_path,
+ key=private_key_path)
+ cache_path = dev_server_cache[update_id]
+ if cache_path:
+ update_url = 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):
+ """Runs the given update cmd given verbose options.
+
+ Raises an UpdateException if the update fails.
+ """
+ if self.verbose:
+ try:
+ RunCommand(cmd)
+ except Exception, e:
+ raise UpdateException(1, e.message)
+ else:
+ (code, stdout, stderr) = RunCommandCaptureOutput(cmd)
+ if code != 0:
+ raise UpdateException(code, stdout)
+
def GetStatefulChangeFlag(self, stateful_change):
"""Returns the flag to pass to image_to_vm for the stateful change."""
stateful_change_flag = ''
@@ -101,7 +166,7 @@ class AUTest(object):
return percent_passed
def PerformUpdate(self, image_path, src_image_path='', stateful_change='old',
- proxy_port=None):
+ 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
@@ -121,10 +186,14 @@ class AUTest(object):
Raises an UpdateException if _UpdateImage returns an error.
"""
try:
- if not self.use_delta_updates:
- src_image_path = ''
+ 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)
+ self._UpdateImage(image_path, src_image_path, stateful_change, proxy_port,
+ key_to_use)
except UpdateException as err:
# If the update fails, print it out
Warning(err.stdout)
@@ -178,6 +247,9 @@ class AUTest(object):
cls.base_image_path = options.base_image
cls.target_image_path = options.target_image
cls.use_delta_updates = options.delta
+ cls.board = options.board
+ cls.private_key = options.private_key
+ cls.clean = options.clean
if options.quick_test:
cls.verify_suite = 'build_RootFilesystemSize'
else:
@@ -199,7 +271,7 @@ class AUTest(object):
pass
def _UpdateImage(self, image_path, src_image_path='', stateful_change='old',
- proxy_port=None):
+ proxy_port=None, private_key_path=None):
"""Implementation of an actual update.
See PerformUpdate for description of args. Subclasses must override this
@@ -410,32 +482,20 @@ class RealAUTest(unittest.TestCase, AUTest):
def PrepareBase(self, image_path):
"""Auto-update to base image to prepare for test."""
- self.PerformUpdate(image_path)
+ _PrepareRealBase(image_path)
def _UpdateImage(self, image_path, src_image_path='', stateful_change='old',
- proxy_port=None):
+ proxy_port=None, private_key_path=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,
stateful_change_flag,
'--verify',
- '--src_image=%s' % src_image_path
]
-
- if proxy_port:
- cmd.append('--proxy_port=%s' % proxy_port)
-
- if self.verbose:
- try:
- RunCommand(cmd)
- except Exception, e:
- raise UpdateException(1, e.message)
- else:
- (code, stdout, stderr) = RunCommandCaptureOutput(cmd)
- if code != 0:
- raise UpdateException(code, stdout)
+ self.AppendUpdateFlags(cmd, image_path, src_image_path, proxy_port,
+ private_key_path)
+ self.RunUpdateCmd(cmd)
def _UpdateUsingPayload(self, update_path, stateful_change='old',
proxy_port=None):
@@ -447,19 +507,8 @@ class RealAUTest(unittest.TestCase, AUTest):
stateful_change_flag,
'--verify',
]
-
- if proxy_port:
- cmd.append('--proxy_port=%s' % proxy_port)
-
- if self.verbose:
- try:
- RunCommand(cmd)
- except Exception, e:
- raise UpdateException(1, e.message)
- else:
- (code, stdout, stderr) = RunCommandCaptureOutput(cmd)
- if code != 0:
- raise UpdateException(code, stdout)
+ if proxy_port: cmd.append('--proxy_port=%s' % proxy_port)
+ self.RunUpdateCmd(cmd)
def VerifyImage(self, percent_required_to_pass):
"""Verifies an image using run_remote_tests.sh with verification suite."""
@@ -474,10 +523,6 @@ class RealAUTest(unittest.TestCase, AUTest):
class VirtualAUTest(unittest.TestCase, AUTest):
"""Test harness for updating virtual machines."""
- # VM Constants.
- _FULL_VDISK_SIZE = 6072
- _FULL_STATEFULFS_SIZE = 3074
-
# Class variables used to acquire individual VM variables per test.
_vm_lock = threading.Lock()
_next_port = 9222
@@ -501,7 +546,6 @@ class VirtualAUTest(unittest.TestCase, AUTest):
def setUp(self):
"""Unit test overriden method. Is called before every test."""
AUTest.setUp(self)
- self.vm_image_path = None
self._AcquireUniquePortAndPidFile()
self._KillExistingVM(self._kvm_pid_file)
@@ -512,85 +556,37 @@ class VirtualAUTest(unittest.TestCase, AUTest):
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.')
+ if not cls.board: parser.error('Need board to convert base image to vm.')
def PrepareBase(self, image_path):
"""Creates an update-able VM based on base image."""
- # 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):
- Info('Creating %s' % vm_image_path)
- RunCommand(['%s/image_to_vm.sh' % self.crosutils,
- '--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,
- '--test_image'], enter_chroot=True)
-
- Info('Using %s as base' % self.vm_image_path)
- self.assertTrue(os.path.exists(self.vm_image_path))
+ self._PrepareVMBase(image_path)
def _UpdateImage(self, image_path, src_image_path='', stateful_change='old',
- proxy_port=''):
+ proxy_port='', private_key_path=None):
"""Updates VM image with image_path."""
stateful_change_flag = self.GetStatefulChangeFlag(stateful_change)
if src_image_path and self._first_update:
src_image_path = self.vm_image_path
self._first_update = False
- # Check image payload cache first.
- update_id = _GenerateUpdateId(target=image_path, src=src_image_path)
- cache_path = dev_server_cache[update_id]
- if cache_path:
- Info('Using cache %s' % cache_path)
- update_url = DevServerWrapper.GetDevServerURL(proxy_port, cache_path)
- cmd = ['%s/cros_run_vm_update' % self.crosutilsbin,
- '--vm_image_path=%s' % self.vm_image_path,
- '--snapshot',
- self.graphics_flag,
- '--persist',
- '--kvm_pid=%s' % self._kvm_pid_file,
- '--ssh_port=%s' % self._ssh_port,
- stateful_change_flag,
- '--update_url=%s' % update_url,
- ]
- else:
- 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,
- '--persist',
- '--kvm_pid=%s' % self._kvm_pid_file,
- '--ssh_port=%s' % self._ssh_port,
- stateful_change_flag,
- '--src_image=%s' % src_image_path,
- '--proxy_port=%s' % proxy_port
- ]
+ cmd = ['%s/cros_run_vm_update' % self.crosutilsbin,
+ '--vm_image_path=%s' % self.vm_image_path,
+ '--snapshot',
+ self.graphics_flag,
+ '--persist',
+ '--kvm_pid=%s' % self._kvm_pid_file,
+ '--ssh_port=%s' % self._ssh_port,
+ stateful_change_flag,
+ ]
- if self.verbose:
- try:
- RunCommand(cmd)
- except Exception, e:
- raise UpdateException(1, e.message)
- else:
- (code, stdout, stderr) = RunCommandCaptureOutput(cmd)
- if code != 0:
- raise UpdateException(code, stdout)
+ self.AppendUpdateFlags(cmd, image_path, src_image_path, proxy_port,
+ private_key_path)
+ self.RunUpdateCmd(cmd)
def _UpdateUsingPayload(self, update_path, stateful_change='old',
proxy_port=None):
@@ -606,19 +602,8 @@ class VirtualAUTest(unittest.TestCase, AUTest):
'--ssh_port=%s' % self._ssh_port,
stateful_change_flag,
]
-
- if proxy_port:
- cmd.append('--proxy_port=%s' % proxy_port)
-
- if self.verbose:
- try:
- RunCommand(cmd)
- except Exception, e:
- raise UpdateException(1, e.message)
- else:
- (code, stdout, stderr) = RunCommandCaptureOutput(cmd)
- if code != 0:
- raise UpdateException(code, stdout)
+ if proxy_port: cmd.append('--proxy_port=%s' % proxy_port)
+ self.RunUpdateCmd(cmd)
def VerifyImage(self, percent_required_to_pass):
"""Runs vm smoke suite to verify image."""
@@ -642,8 +627,12 @@ class VirtualAUTest(unittest.TestCase, AUTest):
return self.AssertEnoughTestsPassed(self, output, percent_required_to_pass)
-class GenerateVirtualAUDeltasTest(VirtualAUTest):
- """Class the overrides VirtualAUTest and stores deltas we will generate."""
+class PregenerateAUDeltas(unittest.TestCase, AUTest):
+ """Magical class that emulates an AUTest to store deltas we will generate.
+
+ This class emulates an AUTest such that when it runs as a TestCase it runs
+ through the exact up
+ """
delta_list = {}
def setUp(self):
@@ -652,16 +641,29 @@ class GenerateVirtualAUDeltasTest(VirtualAUTest):
def tearDown(self):
pass
+ @classmethod
+ def ProcessOptions(cls, parser, options):
+ AUTest.ProcessOptions(parser, options)
+ cls.au_type = options.type
+
+ def PrepareBase(self, image_path):
+ if self.au_type == 'vm':
+ self._PrepareVMBase(image_path)
+ else:
+ self._PrepareRealBase(image_path)
+
def _UpdateImage(self, image_path, src_image_path='', stateful_change='old',
- proxy_port=None):
- if src_image_path and self._first_update:
+ proxy_port=None, private_key_path=None):
+ if self.au_type == 'vm' and src_image_path and self._first_update:
src_image_path = self.vm_image_path
self._first_update = False
+ # Generate a value that combines delta with private key path.
+ val = '%s+%s' % (src_image_path, private_key_path)
if not self.delta_list.has_key(image_path):
- self.delta_list[image_path] = set([src_image_path])
+ self.delta_list[image_path] = set([val])
else:
- self.delta_list[image_path].add(src_image_path)
+ self.delta_list[image_path].add(val)
def AttemptUpdateWithPayloadExpectedFailure(self, payload, expected_msg):
pass
@@ -756,15 +758,16 @@ class DevServerWrapper(threading.Thread):
return url
-def _GenerateUpdateId(target, src):
+def _GenerateUpdateId(target, src, key):
"""Returns a simple representation id of target and src paths."""
- if src:
- return '%s->%s' % (target, src)
- else:
- return target
+ update_id = target
+ if src: update_id = '->'.join([update_id, src])
+ if key: update_id = '+'.join([update_id, key])
+ return update_id
-def _RunParallelJobs(number_of_sumultaneous_jobs, jobs, jobs_args, print_status):
+def _RunParallelJobs(number_of_sumultaneous_jobs, jobs, jobs_args,
+ print_status):
"""Runs set number of specified jobs in parallel.
@@ -834,40 +837,47 @@ def _PregenerateUpdates(parser, options):
Raises:
UpdateException if we fail to generate an update.
"""
- def _GenerateVMUpdate(target, src):
+ def _GenerateVMUpdate(target, src, private_key_path):
"""Generates an update using the devserver."""
- target = ReinterpretPathForChroot(target)
- if src:
- src = ReinterpretPathForChroot(src)
-
- return RunCommandCaptureOutput(['./enter_chroot.sh',
- '--nogit_config',
- '--',
- 'sudo',
- './start_devserver',
- '--pregenerate_update',
- '--exit',
- '--image=%s' % target,
- '--src_image=%s' % src,
- '--for_vm',
- ], combine_stdout_stderr=True,
- print_cmd=False)
+ command = ['./enter_chroot.sh',
+ '--nogit_config',
+ '--',
+ 'sudo',
+ './start_devserver',
+ '--pregenerate_update',
+ '--exit',
+ ]
+ # Add actual args to command.
+ command.append('--image=%s' % ReinterpretPathForChroot(target))
+ if src: command.append('--src_image=%s' % ReinterpretPathForChroot(src))
+ if options.type == 'vm': command.append('--for_vm')
+ if private_key_path:
+ command.append('--private_key=%s' %
+ ReinterpretPathForChroot(private_key_path))
+
+ return RunCommandCaptureOutput(command, combine_stdout_stderr=True,
+ print_cmd=True)
# Get the list of deltas by mocking out update method in test class.
- test_suite = _PrepareTestSuite(parser, options, GenerateVirtualAUDeltasTest)
+ test_suite = _PrepareTestSuite(parser, options, PregenerateAUDeltas)
test_result = unittest.TextTestRunner(verbosity=0).run(test_suite)
+ if not test_result.wasSuccessful():
+ raise UpdateException(1, 'Error finding updates to generate.')
Info('The following delta updates are required.')
update_ids = []
jobs = []
args = []
- for target, srcs in GenerateVirtualAUDeltasTest.delta_list.items():
- for src in srcs:
- update_id = _GenerateUpdateId(target=target, src=src)
+ for target, srcs in PregenerateAUDeltas.delta_list.items():
+ for src_key in srcs:
+ (src, key) = src_key.split('+')
+ # TODO(sosa): Add private key as part of caching name once devserver can
+ # handle it its own cache.
+ update_id = _GenerateUpdateId(target=target, src=src, key=key)
print >> sys.stderr, 'AU: %s' % update_id
update_ids.append(update_id)
jobs.append(_GenerateVMUpdate)
- args.append((target, src))
+ args.append((target, src, key))
raw_results = _RunParallelJobs(options.jobs, jobs, args, print_status=True)
results = []
@@ -919,12 +929,73 @@ def _RunTestsInParallel(parser, options, test_class):
Die('Test harness was not successful')
+def InsertPublicKeyIntoImage(image_path, key_path):
+ """Inserts public key into image @ static update_engine location."""
+ from_dir = os.path.dirname(image_path)
+ image = os.path.basename(image_path)
+ crosutils_dir = os.path.abspath(__file__).rsplit('/', 2)[0]
+ target_key_path = 'usr/share/update_engine/update-payload-key.pub.pem'
+
+ # Temporary directories for this function.
+ rootfs_dir = tempfile.mkdtemp(suffix='rootfs', prefix='tmp')
+ stateful_dir = tempfile.mkdtemp(suffix='stateful', prefix='tmp')
+
+ Info('Copying %s into %s' % (key_path, image_path))
+ try:
+ RunCommand(['./mount_gpt_image.sh',
+ '--from=%s' % from_dir,
+ '--image=%s' % image,
+ '--rootfs_mountpt=%s' % rootfs_dir,
+ '--stateful_mountpt=%s' % stateful_dir,
+ ], print_cmd=False, redirect_stdout=True,
+ redirect_stderr=True, cwd=crosutils_dir)
+ path = os.path.join(rootfs_dir, target_key_path)
+ dir_path = os.path.dirname(path)
+ RunCommand(['sudo', 'mkdir', '--parents', dir_path], print_cmd=False)
+ RunCommand(['sudo', 'cp', '--force', '-p', key_path, path],
+ print_cmd=False)
+ finally:
+ # Unmount best effort regardless.
+ RunCommand(['./mount_gpt_image.sh',
+ '--unmount',
+ '--rootfs_mountpt=%s' % rootfs_dir,
+ '--stateful_mountpt=%s' % stateful_dir,
+ ], print_cmd=False, redirect_stdout=True, redirect_stderr=True,
+ cwd=crosutils_dir)
+ RunCommand(['bin/cros_make_image_bootable', from_dir, image, ],
dgarrett 2011/02/11 01:25:55 Should this be in the finally clause, or unindente
sosa 2011/02/11 21:20:02 Done.
+ print_cmd=False, redirect_stdout=True, redirect_stderr=True,
+ enter_chroot=True, cwd=crosutils_dir)
+ # Clean up our directories.
+ os.rmdir(rootfs_dir)
+ os.rmdir(stateful_dir)
+
+
+def CleanPreviousWork(options):
+ """Cleans up previous work from the devserver cache and local image cache."""
+ Info('Cleaning up previous work.')
+ # Wipe devserver cache.
+ RunCommandCaptureOutput(
+ ['sudo', './start_devserver', '--clear_cache', '--exit', ],
+ enter_chroot=True, print_cmd=False, combine_stdout_stderr=True)
+
+ # Clean previous vm images if they exist.
+ if options.type == 'vm':
+ target_vm_image_path = '%s/chromiumos_qemu_image.bin' % os.path.dirname(
+ options.target_image)
+ base_vm_image_path = '%s/chromiumos_qemu_image.bin' % os.path.dirname(
+ options.base_image)
+ if os.path.exists(target_vm_image_path): os.remove(target_vm_image_path)
+ if os.path.exists(base_vm_image_path): os.remove(base_vm_image_path)
+
+
def main():
parser = optparse.OptionParser()
parser.add_option('-b', '--base_image',
help='path to the base image.')
parser.add_option('-r', '--board',
help='board for the images.')
+ parser.add_option('--clean', default=False, dest='clean', action='store_true',
+ help='Clean all previous state')
parser.add_option('--no_delta', action='store_false', default=True,
dest='delta',
help='Disable using delta updates.')
@@ -932,6 +1003,10 @@ def main():
help='Disable graphics for the vm test.')
parser.add_option('-j', '--jobs', default=8, type=int,
help='Number of simultaneous jobs')
+ parser.add_option('--public_key', default=None,
+ help='Public key to use on images and updates.')
+ parser.add_option('--private_key', default=None,
+ help='Private key to use on images and updates.')
parser.add_option('-q', '--quick_test', default=False, action='store_true',
help='Use a basic test to verify image.')
parser.add_option('-m', '--remote',
@@ -948,31 +1023,48 @@ def main():
'possible.')
(options, leftover_args) = parser.parse_args()
- if leftover_args:
- parser.error('Found extra options we do not support: %s' % leftover_args)
+ if leftover_args: parser.error('Found unsupported flags: %s' % leftover_args)
+
+ assert options.target_image and os.path.exists(options.target_image), \
+ 'Target image path does not exist'
+ if not options.base_image:
+ Info('Base image not specified. Using target image as base image.')
+ options.base_image = options.target_image
+
+ # Sanity checks on keys and insert them onto the image. The caches must be
+ # cleaned so we know that the vm images and payloads match the possibly new
+ # key.
+ if options.private_key or options.public_key:
dgarrett 2011/02/11 01:25:55 If either is specified, you verify that both exist
sosa 2011/02/11 21:20:02 Done.
+ assert os.path.exists(options.private_key), 'Could not find private key.'
+ assert os.path.exists(options.public_key), 'Could not find public key.'
+ InsertPublicKeyIntoImage(options.target_image, options.public_key)
+ InsertPublicKeyIntoImage(options.base_image, options.public_key)
+ options.clean = True
+
+ # Clean up previous work if were requested to.
dgarrett 2011/02/11 01:25:55 s/were/we're/
sosa 2011/02/11 21:20:02 Done.
+ if options.clean: CleanPreviousWork(options)
# Figure out the test_class.
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)
- # TODO(sosa): Caching doesn't really make sense on non-vm images (yet).
+ # Generate cache of updates to use during test harness.
global dev_server_cache
- if options.type == 'vm' and options.jobs > 1:
- dev_server_cache = _PregenerateUpdates(parser, options)
- my_server = DevServerWrapper()
- my_server.start()
- try:
+ dev_server_cache = _PregenerateUpdates(parser, options)
+ my_server = DevServerWrapper()
+ my_server.start()
+ try:
+ if options.type == 'vm':
_RunTestsInParallel(parser, options, test_class)
- finally:
- my_server.Stop()
-
- else:
- dev_server_cache = None
- test_suite = _PrepareTestSuite(parser, options, test_class)
- test_result = unittest.TextTestRunner(verbosity=2).run(test_suite)
- if not test_result.wasSuccessful():
- Die('Test harness was not successful.')
+ else:
+ # TODO(sosa) - Take in a machine pool for a real test.
+ # Can't run in parallel with only one remote device.
+ test_suite = _PrepareTestSuite(parser, options, test_class)
+ test_result = unittest.TextTestRunner(verbosity=2).run(test_suite)
+ if not test_result.wasSuccessful(): Die('Test harness failed.')
+ finally:
+ my_server.Stop()
if __name__ == '__main__':
« no previous file with comments | « no previous file | bin/cros_run_vm_update » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698