mirror of
https://github.com/flatcar/scripts.git
synced 2026-05-04 19:56:32 +02:00
Add testPartialUpdate, testCorruptedUpdate.
Add two new tests that test update-engine handling of a corrupted image, or a truncated image. BUG=chromium-os:9502 TEST=Ran against Dell L13, Mario Review URL: http://codereview.chromium.org/5373008 Change-Id: Ie1043004f01131ea837798c06327c486e1901c15
This commit is contained in:
parent
55430beaef
commit
969a673045
@ -6,14 +6,17 @@
|
||||
|
||||
import optparse
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import unittest
|
||||
import urllib
|
||||
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), '../lib'))
|
||||
from cros_build_lib import Die
|
||||
from cros_build_lib import Info
|
||||
from cros_build_lib import ReinterpretPathForChroot
|
||||
from cros_build_lib import RunCommand
|
||||
from cros_build_lib import RunCommandCaptureOutput
|
||||
from cros_build_lib import Warning
|
||||
|
||||
# VM Constants.
|
||||
@ -29,6 +32,11 @@ global remote
|
||||
global target_image_path
|
||||
global vm_graphics_flag
|
||||
|
||||
class UpdateException(Exception):
|
||||
"""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."""
|
||||
@ -40,6 +48,7 @@ class AUTest(object):
|
||||
# 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__))
|
||||
self.download_folder = os.path.join(self.crosutilsbin, 'latest_download')
|
||||
|
||||
def GetStatefulChangeFlag(self, stateful_change):
|
||||
"""Returns the flag to pass to image_to_vm for the stateful change."""
|
||||
@ -74,11 +83,36 @@ class AUTest(object):
|
||||
Warning('Delta update failed, disabling delta updates and retrying.')
|
||||
self.use_delta_updates = False
|
||||
self.source_image = ''
|
||||
self.UpdateImage(image)
|
||||
self._UpdateImageReportError(image)
|
||||
else:
|
||||
self.UpdateImage(image)
|
||||
self._UpdateImageReportError(image)
|
||||
|
||||
def PrepareBase(self):
|
||||
def _UpdateImageReportError(self, image_path, stateful_change='old'):
|
||||
"""Calls UpdateImage and reports any error to the console.
|
||||
|
||||
Still throws the exception.
|
||||
"""
|
||||
try:
|
||||
self.UpdateImage(image_path, stateful_change)
|
||||
except UpdateException as err:
|
||||
# If the update fails, print it out
|
||||
Warning(err.stdout)
|
||||
raise
|
||||
|
||||
def _AttemptUpdateWithPayloadExpectedFailure(self, payload, expected_msg):
|
||||
# This update is expected to fail...
|
||||
try:
|
||||
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):
|
||||
return
|
||||
|
||||
Warning("Didn't find '%s' in:" % expected_msg)
|
||||
Warning(err.stdout)
|
||||
self.fail('We managed to update when failure was expected')
|
||||
|
||||
def PrepareBase(self, image_path):
|
||||
"""Prepares target with base_image_path."""
|
||||
pass
|
||||
|
||||
@ -95,6 +129,15 @@ class AUTest(object):
|
||||
"""
|
||||
pass
|
||||
|
||||
def UpdateUsingPayload(self, update_path, stateful_change='old'):
|
||||
"""Updates target with the pre-generated update stored in update_path
|
||||
|
||||
Args:
|
||||
update_path: Path to the image to update with. This directory should
|
||||
contain both update.gz, and stateful.image.gz
|
||||
"""
|
||||
pass
|
||||
|
||||
def VerifyImage(self, percent_required_to_pass):
|
||||
"""Verifies the image with tests.
|
||||
|
||||
@ -140,7 +183,7 @@ class AUTest(object):
|
||||
"""
|
||||
# Just make sure some tests pass on original image. Some old images
|
||||
# don't pass many tests.
|
||||
self.PrepareBase()
|
||||
self.PrepareBase(image_path=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)
|
||||
@ -163,7 +206,7 @@ class AUTest(object):
|
||||
"""
|
||||
# Just make sure some tests pass on original image. Some old images
|
||||
# don't pass many tests.
|
||||
self.PrepareBase()
|
||||
self.PrepareBase(image_path=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)
|
||||
@ -178,6 +221,40 @@ class AUTest(object):
|
||||
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(image_path=target_image_path)
|
||||
|
||||
# Image can be updated at:
|
||||
# ~chrome-eng/chromeos/localmirror/autest-images
|
||||
url = 'http://gsdview.appspot.com/chromeos-localmirror/' \
|
||||
'autest-images/truncated_image.gz'
|
||||
payload = os.path.join(self.download_folder, 'truncated_image.gz')
|
||||
|
||||
# Read from the URL and write to the local file
|
||||
urllib.urlretrieve(url, payload)
|
||||
|
||||
expected_msg='download_hash_data == update_check_response_hash failed'
|
||||
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(image_path=target_image_path)
|
||||
|
||||
# Image can be updated at:
|
||||
# ~chrome-eng/chromeos/localmirror/autest-images
|
||||
url = 'http://gsdview.appspot.com/chromeos-localmirror/' \
|
||||
'autest-images/corrupted_image.gz'
|
||||
payload = os.path.join(self.download_folder, 'corrupted.gz')
|
||||
|
||||
# Read from the URL and write to the local file
|
||||
urllib.urlretrieve(url, payload)
|
||||
|
||||
# This update is expected to fail...
|
||||
expected_msg='zlib inflate() error:-3'
|
||||
self._AttemptUpdateWithPayloadExpectedFailure(payload, expected_msg)
|
||||
|
||||
class RealAUTest(unittest.TestCase, AUTest):
|
||||
"""Test harness for updating real images."""
|
||||
@ -185,23 +262,40 @@ class RealAUTest(unittest.TestCase, AUTest):
|
||||
def setUp(self):
|
||||
AUTest.setUp(self)
|
||||
|
||||
def PrepareBase(self):
|
||||
def PrepareBase(self, image_path):
|
||||
"""Auto-update to base image to prepare for test."""
|
||||
self.UpdateImage(base_image_path)
|
||||
self._UpdateImageReportError(image_path)
|
||||
|
||||
def UpdateImage(self, image_path, stateful_change='old'):
|
||||
"""Updates a remote image using image_to_live.sh."""
|
||||
stateful_change_flag = self.GetStatefulChangeFlag(stateful_change)
|
||||
|
||||
RunCommand([
|
||||
(code, stdout, stderr) = RunCommandCaptureOutput([
|
||||
'%s/image_to_live.sh' % self.crosutils,
|
||||
'--image=%s' % image_path,
|
||||
'--remote=%s' % remote,
|
||||
stateful_change_flag,
|
||||
'--verify',
|
||||
'--src_image=%s' % self.source_image,
|
||||
], enter_chroot=False)
|
||||
'--src_image=%s' % self.source_image
|
||||
])
|
||||
|
||||
if code != 0:
|
||||
raise UpdateException(code, stdout)
|
||||
|
||||
def UpdateUsingPayload(self, update_path, stateful_change='old'):
|
||||
"""Updates a remote image using image_to_live.sh."""
|
||||
stateful_change_flag = self.GetStatefulChangeFlag(stateful_change)
|
||||
|
||||
(code, stdout, stderr) = RunCommandCaptureOutput([
|
||||
'%s/image_to_live.sh' % self.crosutils,
|
||||
'--payload=%s' % update_path,
|
||||
'--remote=%s' % remote,
|
||||
stateful_change_flag,
|
||||
'--verify',
|
||||
])
|
||||
|
||||
if code != 0:
|
||||
raise UpdateException(code, stdout)
|
||||
|
||||
def VerifyImage(self, percent_required_to_pass):
|
||||
"""Verifies an image using run_remote_tests.sh with verification suite."""
|
||||
@ -233,17 +327,19 @@ class VirtualAUTest(unittest.TestCase, AUTest):
|
||||
AUTest.setUp(self)
|
||||
self._KillExistingVM(_KVM_PID_FILE)
|
||||
|
||||
def PrepareBase(self):
|
||||
def PrepareBase(self, image_path):
|
||||
"""Creates an update-able VM based on base image."""
|
||||
self.vm_image_path = '%s/chromiumos_qemu_image.bin' % os.path.dirname(
|
||||
base_image_path)
|
||||
image_path)
|
||||
|
||||
Info('Creating: %s' % self.vm_image_path)
|
||||
|
||||
if not os.path.exists(self.vm_image_path):
|
||||
Info('Qemu image %s not found, creating one.' % self.vm_image_path)
|
||||
RunCommand(['%s/image_to_vm.sh' % self.crosutils,
|
||||
'--full',
|
||||
'--from=%s' % ReinterpretPathForChroot(
|
||||
os.path.dirname(base_image_path)),
|
||||
os.path.dirname(image_path)),
|
||||
'--vdisk_size=%s' % _FULL_VDISK_SIZE,
|
||||
'--statefulfs_size=%s' % _FULL_STATEFULFS_SIZE,
|
||||
'--board=%s' % board,
|
||||
@ -251,6 +347,9 @@ class VirtualAUTest(unittest.TestCase, AUTest):
|
||||
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, stateful_change='old'):
|
||||
@ -259,16 +358,41 @@ class VirtualAUTest(unittest.TestCase, AUTest):
|
||||
if self.source_image == base_image_path:
|
||||
self.source_image = self.vm_image_path
|
||||
|
||||
RunCommand(['%s/cros_run_vm_update' % self.crosutilsbin,
|
||||
'--update_image_path=%s' % image_path,
|
||||
'--vm_image_path=%s' % self.vm_image_path,
|
||||
'--snapshot',
|
||||
vm_graphics_flag,
|
||||
'--persist',
|
||||
'--kvm_pid=%s' % _KVM_PID_FILE,
|
||||
stateful_change_flag,
|
||||
'--src_image=%s' % self.source_image,
|
||||
], enter_chroot=False)
|
||||
(code, stdout, stderr) = RunCommandCaptureOutput([
|
||||
'%s/cros_run_vm_update' % self.crosutilsbin,
|
||||
'--update_image_path=%s' % image_path,
|
||||
'--vm_image_path=%s' % self.vm_image_path,
|
||||
'--snapshot',
|
||||
vm_graphics_flag,
|
||||
'--persist',
|
||||
'--kvm_pid=%s' % _KVM_PID_FILE,
|
||||
stateful_change_flag,
|
||||
'--src_image=%s' % self.source_image,
|
||||
])
|
||||
|
||||
if code != 0:
|
||||
raise UpdateException(code, stdout)
|
||||
|
||||
def UpdateUsingPayload(self, update_path, stateful_change='old'):
|
||||
"""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
|
||||
|
||||
(code, stdout, stderr) = RunCommandCaptureOutput([
|
||||
'%s/cros_run_vm_update' % self.crosutilsbin,
|
||||
'--payload=%s' % update_path,
|
||||
'--vm_image_path=%s' % self.vm_image_path,
|
||||
'--snapshot',
|
||||
vm_graphics_flag,
|
||||
'--persist',
|
||||
'--kvm_pid=%s' % _KVM_PID_FILE,
|
||||
stateful_change_flag,
|
||||
'--src_image=%s' % self.source_image,
|
||||
])
|
||||
|
||||
if code != 0:
|
||||
raise UpdateException(code, stdout)
|
||||
|
||||
def VerifyImage(self, percent_required_to_pass):
|
||||
"""Runs vm smoke suite to verify image."""
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
. "$(dirname $0)/../common.sh"
|
||||
. "$(dirname $0)/../lib/cros_vm_lib.sh"
|
||||
|
||||
DEFINE_string payload "" "Full name of the payload to update with."
|
||||
DEFINE_string src_image "" \
|
||||
"Create a delta update by passing in the image on the remote machine."
|
||||
DEFINE_string stateful_update_flag "" "Flags to pass to stateful update." s
|
||||
@ -21,7 +22,7 @@ set -e
|
||||
FLAGS "$@" || exit 1
|
||||
eval set -- "${FLAGS_ARGV}"
|
||||
|
||||
[ -n "${FLAGS_update_image_path}" ] || \
|
||||
[ -n "${FLAGS_update_image_path}" ] || [ -n "${FLAGS_payload}" ] || \
|
||||
die "You must specify a path to an image to use as an update."
|
||||
[ -n "${FLAGS_vm_image_path}" ] || \
|
||||
die "You must specify a path to a vm image."
|
||||
@ -29,6 +30,14 @@ eval set -- "${FLAGS_ARGV}"
|
||||
trap stop_kvm EXIT
|
||||
start_kvm "${FLAGS_vm_image_path}"
|
||||
|
||||
if [ -n "${FLAGS_update_image_path}" ]; then
|
||||
IMAGE_ARGS="--image=$(readlink -f ${FLAGS_update_image_path})"
|
||||
fi
|
||||
|
||||
if [ -n "${FLAGS_payload}" ]; then
|
||||
IMAGE_ARGS="--payload="${FLAGS_payload}""
|
||||
fi
|
||||
|
||||
$(dirname $0)/../image_to_live.sh \
|
||||
--remote=127.0.0.1 \
|
||||
--ssh_port=${FLAGS_ssh_port} \
|
||||
@ -36,5 +45,5 @@ $(dirname $0)/../image_to_live.sh \
|
||||
--src_image="${FLAGS_src_image}" \
|
||||
--verify \
|
||||
--for_vm \
|
||||
--image=$(readlink -f ${FLAGS_update_image_path})
|
||||
${IMAGE_ARGS}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user