|  | #!/bin/bash | 
|  | # | 
|  | # Copyright (C) 2013 The Android Open Source Project | 
|  | # | 
|  | # Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | # you may not use this file except in compliance with the License. | 
|  | # You may obtain a copy of the License at | 
|  | # | 
|  | #      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | # | 
|  | # Unless required by applicable law or agreed to in writing, software | 
|  | # distributed under the License is distributed on an "AS IS" BASIS, | 
|  | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | # See the License for the specific language governing permissions and | 
|  | # limitations under the License. | 
|  | # | 
|  |  | 
|  | # 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 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. 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} | 
|  | } | 
|  |  | 
|  | apply_full_payload() { | 
|  | payload_file=$1 | 
|  | out_dst_kern_part="$2/$3" | 
|  | out_dst_root_part="$2/$4" | 
|  |  | 
|  | time ${paycheck} ${payload_file} \ | 
|  | --out_dst_kern ${out_dst_kern_part} --out_dst_root ${out_dst_root_part} | 
|  | } | 
|  |  | 
|  | apply_delta_payload() { | 
|  | payload_file=$1 | 
|  | out_dst_kern_part="$2/$3" | 
|  | out_dst_root_part="$2/$4" | 
|  | dst_kern_part="$2/$5" | 
|  | dst_root_part="$2/$6" | 
|  | src_kern_part="$2/$7" | 
|  | src_root_part="$2/$8" | 
|  |  | 
|  | time ${paycheck} ${payload_file} \ | 
|  | --out_dst_kern ${out_dst_kern_part} --out_dst_root ${out_dst_root_part} \ | 
|  | --dst_kern ${dst_kern_part} --dst_root ${dst_root_part} \ | 
|  | --src_kern ${src_kern_part} --src_root ${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" | 
|  |  | 
|  | # 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 new full payload..." | 
|  | apply_full_payload "${new_full_payload}" "${tmpdir}" "${NEW_FULL_KERN_PART}" \ | 
|  | "${NEW_FULL_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}" "${NEW_FULL_KERN_PART}" \ | 
|  | "${NEW_FULL_ROOT_PART}" "${OLD_KERN_PART}" "${OLD_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 "$@" |