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