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