summaryrefslogtreecommitdiffstats
path: root/courgette/run_stress_test
blob: dd1a78d88d22f61c9284a43ea648feb4c6fa5c4f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#!/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