test_paycheck.sh 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. #!/bin/bash
  2. #
  3. # Copyright (C) 2013 The Android Open Source Project
  4. #
  5. # Licensed under the Apache License, Version 2.0 (the "License");
  6. # you may not use this file except in compliance with the License.
  7. # You may obtain a copy of the License at
  8. #
  9. # http://www.apache.org/licenses/LICENSE-2.0
  10. #
  11. # Unless required by applicable law or agreed to in writing, software
  12. # distributed under the License is distributed on an "AS IS" BASIS,
  13. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. # See the License for the specific language governing permissions and
  15. # limitations under the License.
  16. #
  17. # A test script for paycheck.py and the update_payload.py library.
  18. #
  19. # This script requires three payload files, along with a metadata signature for
  20. # each, and a public key for verifying signatures. Payload include:
  21. #
  22. # - A full payload for release X (old_full_payload)
  23. #
  24. # - A full payload for release Y (new_full_payload), where Y > X
  25. #
  26. # - A delta payload from X to Y (delta_payload)
  27. #
  28. # The test performs the following:
  29. #
  30. # - It verifies each payload against its metadata signature, also asserting the
  31. # payload type. Another artifact is a human-readable payload report, which
  32. # is output to stdout to be inspected by the user.
  33. #
  34. # - It applies old_full_payload to yield old kernel (old_kern.part) and rootfs
  35. # (old_root.part) partitions.
  36. #
  37. # - It applies delta_payload to old_{kern,root}.part to yield new kernel
  38. # (new_delta_kern.part) and rootfs (new_delta_root.part) partitions.
  39. #
  40. # - It applies new_full_payload to yield reference new kernel
  41. # (new_full_kern.part) and rootfs (new_full_root.part) partitions.
  42. #
  43. # - It compares new_{delta,full}_kern.part and new_{delta,full}_root.part to
  44. # ensure that they are binary identical.
  45. #
  46. # If all steps have completed successfully we know with high certainty that
  47. # paycheck.py (and hence update_payload.py) correctly parses both full and delta
  48. # payloads, and applies them to yield the expected result. Finally, each
  49. # paycheck.py execution is timed.
  50. # Stop on errors, unset variables.
  51. set -e
  52. set -u
  53. # Temporary image files.
  54. OLD_KERN_PART=old_kern.part
  55. OLD_ROOT_PART=old_root.part
  56. NEW_DELTA_KERN_PART=new_delta_kern.part
  57. NEW_DELTA_ROOT_PART=new_delta_root.part
  58. NEW_FULL_KERN_PART=new_full_kern.part
  59. NEW_FULL_ROOT_PART=new_full_root.part
  60. CROS_PARTS="kernel root"
  61. log() {
  62. echo "$@" >&2
  63. }
  64. die() {
  65. log "$@"
  66. exit 1
  67. }
  68. usage_and_exit() {
  69. cat >&2 <<EOF
  70. Usage: ${0##*/} old_full_payload delta_payload new_full_payload
  71. EOF
  72. exit
  73. }
  74. check_payload() {
  75. payload_file=$1
  76. payload_type=$2
  77. time ${paycheck} -t ${payload_type} ${payload_file}
  78. }
  79. apply_full_payload() {
  80. payload_file=$1
  81. out_dst_kern_part="$2/$3"
  82. out_dst_root_part="$2/$4"
  83. time ${paycheck} ${payload_file} \
  84. --part_names ${CROS_PARTS} \
  85. --out_dst_part_paths ${out_dst_kern_part} ${out_dst_root_part}
  86. }
  87. apply_delta_payload() {
  88. payload_file=$1
  89. out_dst_kern_part="$2/$3"
  90. out_dst_root_part="$2/$4"
  91. dst_kern_part="$2/$5"
  92. dst_root_part="$2/$6"
  93. src_kern_part="$2/$7"
  94. src_root_part="$2/$8"
  95. time ${paycheck} ${payload_file} \
  96. --part_names ${CROS_PARTS} \
  97. --out_dst_part_paths ${out_dst_kern_part} ${out_dst_root_part} \
  98. --dst_part_paths ${dst_kern_part} ${dst_root_part} \
  99. --src_part_paths ${src_kern_part} ${src_root_part}
  100. }
  101. main() {
  102. # Read command-line arguments.
  103. if [ $# == 1 ] && [ "$1" == "-h" ]; then
  104. usage_and_exit
  105. elif [ $# != 3 ]; then
  106. die "Error: unexpected number of arguments"
  107. fi
  108. old_full_payload="$1"
  109. delta_payload="$2"
  110. new_full_payload="$3"
  111. # Find paycheck.py
  112. paycheck=${0%/*}/paycheck.py
  113. if [ -z "${paycheck}" ] || [ ! -x ${paycheck} ]; then
  114. die "cannot find ${paycheck} or file is not executable"
  115. fi
  116. # Check the payloads statically.
  117. log "Checking payloads..."
  118. check_payload "${old_full_payload}" full
  119. check_payload "${new_full_payload}" full
  120. check_payload "${delta_payload}" delta
  121. log "Done"
  122. # Apply full/delta payloads and verify results are identical.
  123. tmpdir="$(mktemp -d --tmpdir test_paycheck.XXXXXXXX)"
  124. log "Initiating application of payloads at $tmpdir"
  125. log "Applying old full payload..."
  126. apply_full_payload "${old_full_payload}" "${tmpdir}" "${OLD_KERN_PART}" \
  127. "${OLD_ROOT_PART}"
  128. log "Done"
  129. log "Applying new full payload..."
  130. apply_full_payload "${new_full_payload}" "${tmpdir}" "${NEW_FULL_KERN_PART}" \
  131. "${NEW_FULL_ROOT_PART}"
  132. log "Done"
  133. log "Applying delta payload to old partitions..."
  134. apply_delta_payload "${delta_payload}" "${tmpdir}" "${NEW_DELTA_KERN_PART}" \
  135. "${NEW_DELTA_ROOT_PART}" "${NEW_FULL_KERN_PART}" \
  136. "${NEW_FULL_ROOT_PART}" "${OLD_KERN_PART}" "${OLD_ROOT_PART}"
  137. log "Done"
  138. log "Comparing results of delta and new full updates..."
  139. diff "${tmpdir}/${NEW_FULL_KERN_PART}" "${tmpdir}/${NEW_DELTA_KERN_PART}"
  140. diff "${tmpdir}/${NEW_FULL_ROOT_PART}" "${tmpdir}/${NEW_DELTA_ROOT_PART}"
  141. log "Done"
  142. log "Cleaning up"
  143. rm -fr "${tmpdir}"
  144. }
  145. main "$@"