#!/bin/bash # Copyright 2013 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # Stress test and size measurement for courgette patches. source "$(dirname ${0})/stress_test_common" outdir_prefix="stress_test_" time="/usr/bin/time" if [ $# -lt 2 ]; then cat <<EOF USAGE: $(basename ${0}) [-s] dir1 dir2 [outdir] -s only test files supported by courgette Stress test courgette by generating and applying patches for two given directories, dir1 and dir2. The test will use files with the same name and relative path in the two directories, which makes it easy to compare two extracted ChromeOS images. It also compares the unzipped and bzipped patches against the likewise bsdiff patches. If outdir is not specified, the name will be "${outdir_prefix}" concatenated with the current date and time. EOF exit 1 fi if [ "${1}" == "-s" ]; then test_supported_only=true shift else test_supported_only= fi dir1="${1}" if [ ! -e "${dir1}" ]; then error "\"${dir1}\" not found" exit 1 fi dir2="${2}" if [ ! -e "${dir2}" ]; then error "\"${dir2}\" not found" exit 1 fi out_dir="${3:-${outdir_prefix}$(date +%Y%m%d_%H%M%S)}" if [ -e "${out_dir}" ]; then error "\"${out_dir}\" already exists" exit 1 fi mkdir -p "${out_dir}" || exit 1 patches_dir="${out_dir}/patches" applied_dir="${out_dir}/applied" dis_dir="${out_dir}/dis" bsdiff="${out_dir}/bsdiff" log="${out_dir}/log" results="${out_dir}/results" echo "${0} ${@}" > "${log}" date >> "${log}" run_test() { if [[ ! -z "${1}" && ! -z "${2}" ]]; then local file1="${1}" local file2="${2}" local patch="${patches_dir}/${file1}.patch" local apply="${applied_dir}/${file2}.applied" local dis="${dis_dir}/${file1}.dis" local asm="${dis_dir}/${file1}.asm" mkdir -p "$(dirname "${dis}")" if [ ! $test_supported_only ]; then courgette -supported "${file1}" >/dev/null if [ "${?}" -eq 0 ]; then courgette -dis "${file1}" "${dis}" courgette -asm "${dis}" "${asm}" cmp -s "${file1}" "${asm}" if [ "${?}" -ne 0 ]; then echo "FAIL_DISASSEMBLE ${file1}" fi fi fi mkdir -p "$(dirname "${patch}")" mkdir -p "$(dirname "${apply}")" echo "courgette -gen" ${time} -f "TIME_GEN %e ${file1}" courgette -gen "${file1}" "${file2}" \ "${patch}" echo "courgette -apply" ${time} -f "TIME_APPLY %e ${file1}" courgette -apply "${file1}" "${patch}" \ "${apply}" cmp -s "${file2}" "${apply}" if [ "${?}" -ne 0 ]; then echo "FAIL_COURGETTE ${file1}" else echo "PASS_COURGETTE ${file1}" local bsdiff_patch="${patches_dir}/${file1}.bsdiff_patch" local bsdiff_apply="${applied_dir}/${file2}.bsdiff_applied" echo "RUN bsdiff" ${time} -f "TIME_BSDIFF %e ${file1}" bsdiff "${file1}" "${file2}" \ "${bsdiff_patch}" echo "RUN bspatch" ${time} -f "TIME_BSPATCH %e ${file1}" bspatch "${file1}" \ "${bsdiff_apply}" "${bsdiff_patch}" cmp -s "${file2}" "${bsdiff_apply}" if [ "${?}" -ne 0 ]; then echo "FAIL_BSDIFF ${file1}" else echo "PASS_BSDIFF ${file1}" local bz2_patch="${patch}.bz2" local xz_patch="${patch}.xz" bzip2 -9 -c "${patch}" > "${bz2_patch}" xz -9 -c "${patch}" > "${xz_patch}" local patch_size="$(du -b "${bz2_patch}" | cut -f1)" local bsdiff_patch_size="$(du -b "${bsdiff_patch}" | cut -f1)" local xz_patch_size="$(du -b "${xz_patch}" | cut -f1)" echo "SIZE courgette=${patch_size} bsdiff=${bsdiff_patch_size}" \ "courgette_xz=${xz_patch_size} ${file1}" if [ "${patch_size}" -eq "${bsdiff_patch_size}" ]; then echo "BEST_TIE ${patch_size} ${file1}" elif [ "${patch_size}" -lt "${bsdiff_patch_size}" ]; then echo "BEST_COURGETTE ${patch_size} ${file1}" elif [ "${patch_size}" -gt "${bsdiff_patch_size}" ]; then echo "BEST_BSDIFF ${bsdiff_patch_size} ${file1}" fi if [ "${xz_patch_size}" -eq "${bsdiff_patch_size}" ]; then echo "XZBEST_TIE ${xz_patch_size} ${file1}" elif [ "${xz_patch_size}" -lt "${bsdiff_patch_size}" ]; then echo "XZBEST_COURGETTE ${xz_patch_size} ${file1}" elif [ "${xz_patch_size}" -gt "${bsdiff_patch_size}" ]; then echo "XZBEST_BSDIFF ${bsdiff_patch_size} ${file1}" fi fi fi fi } # Use diff to find the files that appear in both directories. time diff -qr "${dir1}" "${dir2}" 2>/dev/null \ | grep "^Files" \ | awk '{print $2,$4}' \ | while read file; do # Use awk to separate the two filenames. May break if filenames # contain spaces. file1="$(echo "${file}" | awk '{print $1}')" file2="$(echo "${file}" | awk '{print $2}')" if [ $test_supported_only ]; then courgette -supported "${file1}" >/dev/null if [ "${?}" -ne 0 ]; then continue; fi fi run_test "${file1}" "${file2}" done 2>&1 | tee -a "${log}" date >> "${log}" cat <<EOF | tee -a "${log}" $(count_result "PASS_COURGETTE") successful courgette patches $(count_result "FAIL_COURGETTE") failed courgette patches (search log for \ "^FAIL_COURGETTE") $(count_result "FAIL_DISASSEMBLE") failed to disassemble/assemble (search log \ for "^FAIL_DISASSEMBLE") $(count_result "PASS_BSDIFF") succesful bsdiff patches $(count_result "FAIL_BSDIFF") failed bsdiff patches $(count_result "BEST_COURGETTE") patch(es) where courgette (bz2) is smaller $(count_result "BEST_BSDIFF") patch(es) where bsdiff is smaller (bz2) $(count_result "BEST_TIE") patch(es) where both are the same size (bz2) $(count_result "XZBEST_COURGETTE") patch(es) where courgette (xz) is smaller $(count_result "XZBEST_BSDIFF") patch(es) where bsdiff is smaller (xz) $(count_result "XZBEST_TIE") patch(es) where both are the same size (xz) EOF