175 lines
5 KiB
Bash
Executable file
175 lines
5 KiB
Bash
Executable file
#!/bin/bash
|
|
#
|
|
# Copyright (c) 2013 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.
|
|
|
|
# A test script for paycheck.py and the update_payload.py library.
|
|
#
|
|
# This script requires three payload files, along with a metadata signature for
|
|
# each, and a public key for verifying signatures. Payload include:
|
|
#
|
|
# - A full payload for release X (old_full_payload)
|
|
#
|
|
# - A full payload for release Y (new_full_payload), where Y > X
|
|
#
|
|
# - A delta payload from X to Y (delta_payload)
|
|
#
|
|
# The test performs the following:
|
|
#
|
|
# - It verifies each payload against its metadata signature, also asserting the
|
|
# payload type. Another artifact is a human-readable payload report, which
|
|
# is output to stdout to be inspected by the user.
|
|
#
|
|
# - It performs a random block trace on the delta payload (both kernel and
|
|
# rootfs blocks), dumping the traces to stdout for the user to inspect.
|
|
#
|
|
# - It applies old_full_payload to yield old kernel (old_kern.part) and rootfs
|
|
# (old_root.part) partitions.
|
|
#
|
|
# - It applies delta_payload to old_{kern,root}.part to yield new kernel
|
|
# (new_delta_kern.part) and rootfs (new_delta_root.part) partitions.
|
|
#
|
|
# - It applies new_full_payload to yield reference new kernel
|
|
# (new_full_kern.part) and rootfs (new_full_root.part) partitions.
|
|
#
|
|
# - It compares new_{delta,full}_kern.part and new_{delta,full}_root.part to
|
|
# ensure that they are binary identical.
|
|
#
|
|
# If all steps have completed successfully we know with high certainty that
|
|
# paycheck.py (and hence update_payload.py) correctly parses both full and
|
|
# delta payloads, and applies them to yield the expected result. We also know
|
|
# that tracing works, to the extent it does not crash. Manual inspection of
|
|
# payload reports and block traces will improve this our confidence and are
|
|
# strongly encouraged. Finally, each paycheck.py execution is timed.
|
|
|
|
|
|
# Stop on errors, unset variables.
|
|
set -e
|
|
set -u
|
|
|
|
# Temporary image files.
|
|
OLD_KERN_PART=old_kern.part
|
|
OLD_ROOT_PART=old_root.part
|
|
NEW_DELTA_KERN_PART=new_delta_kern.part
|
|
NEW_DELTA_ROOT_PART=new_delta_root.part
|
|
NEW_FULL_KERN_PART=new_full_kern.part
|
|
NEW_FULL_ROOT_PART=new_full_root.part
|
|
|
|
|
|
log() {
|
|
echo "$@" >&2
|
|
}
|
|
|
|
die() {
|
|
log "$@"
|
|
exit 1
|
|
}
|
|
|
|
usage_and_exit() {
|
|
cat >&2 <<EOF
|
|
Usage: ${0##*/} old_full_payload delta_payload new_full_payload
|
|
EOF
|
|
exit
|
|
}
|
|
|
|
check_payload() {
|
|
payload_file=$1
|
|
payload_type=$2
|
|
|
|
time ${paycheck} -t ${payload_type} ${payload_file}
|
|
}
|
|
|
|
trace_kern_block() {
|
|
payload_file=$1
|
|
block=$2
|
|
time ${paycheck} -B ${block} ${payload_file}
|
|
}
|
|
|
|
trace_root_block() {
|
|
payload_file=$1
|
|
block=$2
|
|
time ${paycheck} -b ${block} ${payload_file}
|
|
}
|
|
|
|
apply_full_payload() {
|
|
payload_file=$1
|
|
dst_kern_part="$2/$3"
|
|
dst_root_part="$2/$4"
|
|
|
|
time ${paycheck} ${payload_file} ${dst_kern_part} ${dst_root_part}
|
|
}
|
|
|
|
apply_delta_payload() {
|
|
payload_file=$1
|
|
dst_kern_part="$2/$3"
|
|
dst_root_part="$2/$4"
|
|
src_kern_part="$2/$5"
|
|
src_root_part="$2/$6"
|
|
|
|
time ${paycheck} ${payload_file} ${dst_kern_part} ${dst_root_part} \
|
|
${src_kern_part} ${src_root_part}
|
|
}
|
|
|
|
main() {
|
|
# Read command-line arguments.
|
|
if [ $# == 1 ] && [ "$1" == "-h" ]; then
|
|
usage_and_exit
|
|
elif [ $# != 3 ]; then
|
|
die "Error: unexpected number of arguments"
|
|
fi
|
|
old_full_payload="$1"
|
|
delta_payload="$2"
|
|
new_full_payload="$3"
|
|
|
|
# Find paycheck.py
|
|
paycheck=${0%/*}/paycheck.py
|
|
if [ -z "${paycheck}" ] || [ ! -x ${paycheck} ]; then
|
|
die "cannot find ${paycheck} or file is not executable"
|
|
fi
|
|
|
|
# Check the payloads statically.
|
|
log "Checking payloads..."
|
|
check_payload "${old_full_payload}" full
|
|
check_payload "${new_full_payload}" full
|
|
check_payload "${delta_payload}" delta
|
|
log "Done"
|
|
|
|
# Trace a random block between 0-1024 on all payloads.
|
|
block=$((RANDOM * 1024 / 32767))
|
|
log "Tracing a random block (${block}) in full/delta payloads..."
|
|
trace_kern_block "${new_full_payload}" ${block}
|
|
trace_root_block "${new_full_payload}" ${block}
|
|
trace_kern_block "${delta_payload}" ${block}
|
|
trace_root_block "${delta_payload}" ${block}
|
|
log "Done"
|
|
|
|
# Apply full/delta payloads and verify results are identical.
|
|
tmpdir="$(mktemp -d --tmpdir test_paycheck.XXXXXXXX)"
|
|
log "Initiating application of payloads at $tmpdir"
|
|
|
|
log "Applying old full payload..."
|
|
apply_full_payload "${old_full_payload}" "${tmpdir}" "${OLD_KERN_PART}" \
|
|
"${OLD_ROOT_PART}"
|
|
log "Done"
|
|
|
|
log "Applying delta payload to old partitions..."
|
|
apply_delta_payload "${delta_payload}" "${tmpdir}" "${NEW_DELTA_KERN_PART}" \
|
|
"${NEW_DELTA_ROOT_PART}" "${OLD_KERN_PART}" "${OLD_ROOT_PART}"
|
|
log "Done"
|
|
|
|
log "Applying new full payload..."
|
|
apply_full_payload "${new_full_payload}" "${tmpdir}" "${NEW_FULL_KERN_PART}" \
|
|
"${NEW_FULL_ROOT_PART}"
|
|
log "Done"
|
|
|
|
log "Comparing results of delta and new full updates..."
|
|
diff "${tmpdir}/${NEW_FULL_KERN_PART}" "${tmpdir}/${NEW_DELTA_KERN_PART}"
|
|
diff "${tmpdir}/${NEW_FULL_ROOT_PART}" "${tmpdir}/${NEW_DELTA_ROOT_PART}"
|
|
log "Done"
|
|
|
|
log "Cleaning up"
|
|
rm -fr "${tmpdir}"
|
|
}
|
|
|
|
main "$@"
|