1 #!/bin/bash 2 3 # Copyright 2013 The Chromium Authors. All rights reserved. 4 # Use of this source code is governed by a BSD-style license that can be 5 # found in the LICENSE file. 6 7 # Stress test and size measurement for courgette patches. 8 9 source "$(dirname ${0})/stress_test_common" 10 11 outdir_prefix="stress_test_" 12 time="/usr/bin/time" 13 14 if [ $# -lt 2 ]; then 15 cat <<EOF 16 17 USAGE: $(basename ${0}) [-s] dir1 dir2 [outdir] 18 19 -s only test files supported by courgette 20 21 Stress test courgette by generating and applying patches for two given 22 directories, dir1 and dir2. The test will use files with the same 23 name and relative path in the two directories, which makes it easy to 24 compare two extracted ChromeOS images. It also compares the unzipped 25 and bzipped patches against the likewise bsdiff patches. If outdir is 26 not specified, the name will be "${outdir_prefix}" concatenated with 27 the current date and time. 28 29 EOF 30 exit 1 31 fi 32 33 if [ "${1}" == "-s" ]; then 34 test_supported_only=true 35 shift 36 else 37 test_supported_only= 38 fi 39 40 dir1="${1}" 41 if [ ! -e "${dir1}" ]; then 42 error "\"${dir1}\" not found" 43 exit 1 44 fi 45 46 dir2="${2}" 47 if [ ! -e "${dir2}" ]; then 48 error "\"${dir2}\" not found" 49 exit 1 50 fi 51 52 out_dir="${3:-${outdir_prefix}$(date +%Y%m%d_%H%M%S)}" 53 if [ -e "${out_dir}" ]; then 54 error "\"${out_dir}\" already exists" 55 exit 1 56 fi 57 58 mkdir -p "${out_dir}" || exit 1 59 60 patches_dir="${out_dir}/patches" 61 applied_dir="${out_dir}/applied" 62 dis_dir="${out_dir}/dis" 63 bsdiff="${out_dir}/bsdiff" 64 log="${out_dir}/log" 65 results="${out_dir}/results" 66 67 echo "${0} ${@}" > "${log}" 68 date >> "${log}" 69 70 run_test() { 71 if [[ ! -z "${1}" && ! -z "${2}" ]]; then 72 local file1="${1}" 73 local file2="${2}" 74 local patch="${patches_dir}/${file1}.patch" 75 local apply="${applied_dir}/${file2}.applied" 76 local dis="${dis_dir}/${file1}.dis" 77 local asm="${dis_dir}/${file1}.asm" 78 mkdir -p "$(dirname "${dis}")" 79 if [ ! $test_supported_only ]; then 80 courgette -supported "${file1}" >/dev/null 81 if [ "${?}" -eq 0 ]; then 82 courgette -dis "${file1}" "${dis}" 83 courgette -asm "${dis}" "${asm}" 84 cmp -s "${file1}" "${asm}" 85 if [ "${?}" -ne 0 ]; then 86 echo "FAIL_DISASSEMBLE ${file1}" 87 fi 88 fi 89 fi 90 mkdir -p "$(dirname "${patch}")" 91 mkdir -p "$(dirname "${apply}")" 92 echo "courgette -gen" 93 ${time} -f "TIME_GEN %e ${file1}" courgette -gen "${file1}" "${file2}" \ 94 "${patch}" 95 echo "courgette -apply" 96 ${time} -f "TIME_APPLY %e ${file1}" courgette -apply "${file1}" "${patch}" \ 97 "${apply}" 98 cmp -s "${file2}" "${apply}" 99 if [ "${?}" -ne 0 ]; then 100 echo "FAIL_COURGETTE ${file1}" 101 else 102 echo "PASS_COURGETTE ${file1}" 103 local bsdiff_patch="${patches_dir}/${file1}.bsdiff_patch" 104 local bsdiff_apply="${applied_dir}/${file2}.bsdiff_applied" 105 echo "RUN bsdiff" 106 ${time} -f "TIME_BSDIFF %e ${file1}" bsdiff "${file1}" "${file2}" \ 107 "${bsdiff_patch}" 108 echo "RUN bspatch" 109 ${time} -f "TIME_BSPATCH %e ${file1}" bspatch "${file1}" \ 110 "${bsdiff_apply}" "${bsdiff_patch}" 111 cmp -s "${file2}" "${bsdiff_apply}" 112 if [ "${?}" -ne 0 ]; then 113 echo "FAIL_BSDIFF ${file1}" 114 else 115 echo "PASS_BSDIFF ${file1}" 116 local bz2_patch="${patch}.bz2" 117 local xz_patch="${patch}.xz" 118 bzip2 -9 -c "${patch}" > "${bz2_patch}" 119 xz -9 -c "${patch}" > "${xz_patch}" 120 local patch_size="$(du -b "${bz2_patch}" | cut -f1)" 121 local bsdiff_patch_size="$(du -b "${bsdiff_patch}" | cut -f1)" 122 local xz_patch_size="$(du -b "${xz_patch}" | cut -f1)" 123 echo "SIZE courgette=${patch_size} bsdiff=${bsdiff_patch_size}" \ 124 "courgette_xz=${xz_patch_size} ${file1}" 125 if [ "${patch_size}" -eq "${bsdiff_patch_size}" ]; then 126 echo "BEST_TIE ${patch_size} ${file1}" 127 elif [ "${patch_size}" -lt "${bsdiff_patch_size}" ]; then 128 echo "BEST_COURGETTE ${patch_size} ${file1}" 129 elif [ "${patch_size}" -gt "${bsdiff_patch_size}" ]; then 130 echo "BEST_BSDIFF ${bsdiff_patch_size} ${file1}" 131 fi 132 if [ "${xz_patch_size}" -eq "${bsdiff_patch_size}" ]; then 133 echo "XZBEST_TIE ${xz_patch_size} ${file1}" 134 elif [ "${xz_patch_size}" -lt "${bsdiff_patch_size}" ]; then 135 echo "XZBEST_COURGETTE ${xz_patch_size} ${file1}" 136 elif [ "${xz_patch_size}" -gt "${bsdiff_patch_size}" ]; then 137 echo "XZBEST_BSDIFF ${bsdiff_patch_size} ${file1}" 138 fi 139 fi 140 fi 141 fi 142 } 143 144 # Use diff to find the files that appear in both directories. 145 time diff -qr "${dir1}" "${dir2}" 2>/dev/null \ 146 | grep "^Files" \ 147 | awk '{print $2,$4}' \ 148 | while read file; do 149 # Use awk to separate the two filenames. May break if filenames 150 # contain spaces. 151 file1="$(echo "${file}" | awk '{print $1}')" 152 file2="$(echo "${file}" | awk '{print $2}')" 153 if [ $test_supported_only ]; then 154 courgette -supported "${file1}" >/dev/null 155 if [ "${?}" -ne 0 ]; then 156 continue; 157 fi 158 fi 159 run_test "${file1}" "${file2}" 160 done 2>&1 | tee -a "${log}" 161 162 date >> "${log}" 163 164 cat <<EOF | tee -a "${log}" 165 $(count_result "PASS_COURGETTE") successful courgette patches 166 $(count_result "FAIL_COURGETTE") failed courgette patches (search log for \ 167 "^FAIL_COURGETTE") 168 $(count_result "FAIL_DISASSEMBLE") failed to disassemble/assemble (search log \ 169 for "^FAIL_DISASSEMBLE") 170 $(count_result "PASS_BSDIFF") succesful bsdiff patches 171 $(count_result "FAIL_BSDIFF") failed bsdiff patches 172 $(count_result "BEST_COURGETTE") patch(es) where courgette (bz2) is smaller 173 $(count_result "BEST_BSDIFF") patch(es) where bsdiff is smaller (bz2) 174 $(count_result "BEST_TIE") patch(es) where both are the same size (bz2) 175 $(count_result "XZBEST_COURGETTE") patch(es) where courgette (xz) is smaller 176 $(count_result "XZBEST_BSDIFF") patch(es) where bsdiff is smaller (xz) 177 $(count_result "XZBEST_TIE") patch(es) where both are the same size (xz) 178 EOF 179