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 9error() { 10 echo "error: ${@}" >&2 11} 12 13outdir_prefix="stress_test_" 14 15if [ $# -lt 2 ]; then 16 cat <<EOF 17 18USAGE: $(basename ${0}) [-s] dir1 dir2 [outdir] 19 20 -s only test files supported by courgette 21 22Stress test courgette by generating and applying patches for two given 23directories, dir1 and dir2. The test will use files with the same 24name and relative path in the two directories, which makes it easy to 25compare two extracted ChromeOS images. It also compares the unzipped 26and bzipped patches against the likewise bsdiff patches. If outdir is 27not specified, the name will be "${outdir_prefix}" concatenated with 28the current date and time. 29 30EOF 31 exit 1 32fi 33 34if [ "${1}" == "-s" ]; then 35 test_supported_only=true 36 shift 37else 38 test_supported_only= 39fi 40 41dir1="${1}" 42if [ ! -e "${dir1}" ]; then 43 error "\"${dir1}\" not found" 44 exit 1 45fi 46 47dir2="${2}" 48if [ ! -e "${dir2}" ]; then 49 error "\"${dir2}\" not found" 50 exit 1 51fi 52 53out_dir="${3:-${outdir_prefix}$(date +%Y%m%d_%H%M%S)}" 54if [ -e "${out_dir}" ]; then 55 error "\"${out_dir}\" already exists" 56 exit 1 57fi 58 59mkdir -p "${out_dir}" || exit 1 60 61patches_dir="${out_dir}/patches" 62applied_dir="${out_dir}/applied" 63dis_dir="${out_dir}/dis" 64bsdiff="${out_dir}/bsdiff" 65log="${out_dir}/log" 66results="${out_dir}/results" 67 68echo "${0} ${@}" > "${log}" 69date >> "${log}" 70 71run_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. 126time 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}" 141done 2>&1 | tee -a "${log}" 142 143date >> "${log}" 144 145count_result() { 146 if [ ! -z "${1}" ]; then 147 echo $(cat "${log}" | grep "^${1} " | wc -l) 148 else 149 echo 0 150 fi 151} 152 153cat <<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 \ 158for "^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 164EOF 165