Home | History | Annotate | Download | only in courgette
      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