blob: dfe11299c8f262a22a3d436c3f9f18013342237f [file] [log] [blame]
#!/usr/bin/python
# Copyright (c) 2014 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.
"""Integration test to test the basic functionality of cros flash/deploy.
This module contains a test that runs some sanity integration tests against
a VM. It starts a VM and runs `cros flash` to update the VM, and then
`cros deploy` to install packages to the VM.
"""
from __future__ import print_function
import logging
from chromite.lib import commandline
from chromite.lib import cros_build_lib
from chromite.lib import osutils
from chromite.lib import remote_access
from chromite.lib import vm
def _FormatLogContent(name, content):
"""Helper function for printing out complete log content."""
return '\n'.join((
'----------- Start of %s log -----------\n' % name,
content,
'----------- End of %s log -----------\n' % name,
))
class TestError(Exception):
"""Raised on any error during testing."""
class CrosCommandTest(object):
"""Wrapper cros command tests."""
def __init__(self, board, image_path):
"""Initialize CrosTest.
Args:
board: Board of the image under test.
image_path: Path to the VM image to test.
"""
self.board = board
self.image_path = image_path
self.working_image_path = None
self.vm = None
def Cleanup(self):
"""Cleans up any state at the end of the test."""
try:
if self.vm:
self.vm.Stop()
self.vm = None
except Exception:
logging.warning('Received error during cleanup', exc_info=True)
def Setup(self):
"""Creates and/or starts the VM instance."""
logging.info('Setting up image %s for vm testing.', self.image_path)
self.working_image_path = vm.CreateVMImage(
image=self.image_path, board=self.board, updatable=True,
dest_dir=self.tempdir)
logging.info('Using VM image at %s.', self.working_image_path)
self.vm = vm.VMInstance(self.working_image_path, tempdir=self.tempdir)
logging.info('Starting the vm on port %d.', self.vm.port)
self.vm.Start()
def TestCrosFlash(self):
"""Tests that we can flash the device with the latest image."""
logging.info('Testing flashing VM with cros flash...')
device_addr = 'ssh://%s:%d' % (remote_access.LOCALHOST, self.vm.port)
# We explicitly disable reboot after the update because VMs
# sometimes do not come back after reboot. `cros flash` does not
# need to verify the integrity of the updated image. We have AU
# tests for that.
cmd = ['cros', 'flash', '--debug', '--no-wipe', '--no-reboot',
device_addr, 'latest']
result = cros_build_lib.RunCommand(cmd, capture_output=True,
error_code_ok=True)
if result.returncode != 0:
logging.error('Failed updating VM with image. Printing logs...\n%s',
_FormatLogContent('Cros Flash', result.error))
raise TestError('cros flash test failed')
logging.info('cros flash test completed successfully')
def TestCrosDeploy(self):
"""Tests that we can deploy packages to the device."""
logging.info('Testing installing/uninstalling pacakges with cros deploy...')
device_addr = 'ssh://%s:%d' % (remote_access.LOCALHOST, self.vm.port)
packages = ['dev-python/cherrypy', 'app-portage/portage-utils']
# Set the installation root to /usr/local so that `cros deploy`
# does not attempt to remount rootfs (which leads to VM reboot).
cmd_base = ['cros', 'deploy', '--debug', '--root=/usr/local', device_addr]
# Unmerge the packages.
cmd = cmd_base + ['--unmerge'] + packages
result = cros_build_lib.RunCommand(cmd, capture_output=True,
enter_chroot=True,
error_code_ok=True)
if result.returncode != 0:
logging.error('Failed unmerging packages from VM. Printing logs...\n%s',
_FormatLogContent('Cros Deploy', result.error))
raise TestError('cros deploy unmerge test failed.')
# Re-install the packages.
cmd = cmd_base + packages
result = cros_build_lib.RunCommand(cmd, capture_output=True,
enter_chroot=True,
error_code_ok=True)
if result.returncode != 0:
logging.error('Failed deploying packages to VM. Printing logs...\n%s',
_FormatLogContent('Cros Deploy', result.error))
raise TestError('cros deploy test failed.')
# Verify that the packages are installed.
with remote_access.ChromiumOSDeviceHandler(
remote_access.LOCALHOST, port=self.vm.port,
base_dir=self.tempdir) as device:
try:
device.RunCommand(['python', '-c', '"import cherrypy"'])
device.RunCommand(['qmerge', '-h'])
except remote_access.SSHConnectionError as e:
logging.error('Unable to connect to VM after deploy packages')
raise TestError('Unable to connect to VM: %s' % str(e))
except cros_build_lib.RunCommandError as e:
logging.error('Could not verify packages are installed')
raise TestError('Error verifying packages are installed: %s' % str(e))
logging.info('cros deploy test completed successfully')
@osutils.TempDirDecorator
def Run(self):
"""Runs the tests."""
try:
self.Setup()
self.TestCrosFlash()
self.TestCrosDeploy()
finally:
self.Cleanup()
logging.info('All tests in cros_vm_test passed.')
def _ParseArguments(argv):
"""Parses command line arguments."""
parser = commandline.ArgumentParser(caching=True)
parser.add_argument(
'board', help='Board of the image.')
parser.add_argument(
'image_path', help='Path to the image to test.')
return parser.parse_args(argv)
def main(argv):
"""Main function of the script."""
options = _ParseArguments(argv)
options.Freeze()
logging.info('Starting cros_vm_test...')
test = CrosCommandTest(options.board, options.image_path)
test.Run()