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 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