t / t5303-pack-corruption-resilience.shon commit Merge branch 'jn/gitweb-customlinks' (168d5bd)
   1#!/bin/sh
   2#
   3# Copyright (c) 2008 Nicolas Pitre
   4#
   5
   6test_description='resilience to pack corruptions with redundant objects'
   7. ./test-lib.sh
   8
   9# Note: the test objects are created with knowledge of their pack encoding
  10# to ensure good code path coverage, and to facilitate direct alteration
  11# later on.  The assumed characteristics are:
  12#
  13# 1) blob_2 is a delta with blob_1 for base and blob_3 is a delta with blob2
  14#    for base, such that blob_3 delta depth is 2;
  15#
  16# 2) the bulk of object data is uncompressible so the text part remains
  17#    visible;
  18#
  19# 3) object header is always 2 bytes.
  20
  21create_test_files() {
  22    test-genrandom "foo" 2000 > file_1 &&
  23    test-genrandom "foo" 1800 > file_2 &&
  24    test-genrandom "foo" 1800 > file_3 &&
  25    echo " base " >> file_1 &&
  26    echo " delta1 " >> file_2 &&
  27    echo " delta delta2 " >> file_3 &&
  28    test-genrandom "bar" 150 >> file_2 &&
  29    test-genrandom "baz" 100 >> file_3
  30}
  31
  32create_new_pack() {
  33    rm -rf .git &&
  34    git init &&
  35    blob_1=`git hash-object -t blob -w file_1` &&
  36    blob_2=`git hash-object -t blob -w file_2` &&
  37    blob_3=`git hash-object -t blob -w file_3` &&
  38    pack=`printf "$blob_1\n$blob_2\n$blob_3\n" |
  39          git pack-objects $@ .git/objects/pack/pack` &&
  40    pack=".git/objects/pack/pack-${pack}" &&
  41    git verify-pack -v ${pack}.pack
  42}
  43
  44do_repack() {
  45    pack=`printf "$blob_1\n$blob_2\n$blob_3\n" |
  46          git pack-objects $@ .git/objects/pack/pack` &&
  47    pack=".git/objects/pack/pack-${pack}"
  48}
  49
  50do_corrupt_object() {
  51    ofs=`git show-index < ${pack}.idx | grep $1 | cut -f1 -d" "` &&
  52    ofs=$(($ofs + $2)) &&
  53    chmod +w ${pack}.pack &&
  54    dd of=${pack}.pack count=1 bs=1 conv=notrunc seek=$ofs &&
  55    test_must_fail git verify-pack ${pack}.pack
  56}
  57
  58test_expect_success \
  59    'initial setup validation' \
  60    'create_test_files &&
  61     create_new_pack &&
  62     git prune-packed &&
  63     git cat-file blob $blob_1 > /dev/null &&
  64     git cat-file blob $blob_2 > /dev/null &&
  65     git cat-file blob $blob_3 > /dev/null'
  66
  67test_expect_success \
  68    'create corruption in header of first object' \
  69    'do_corrupt_object $blob_1 0 < /dev/zero &&
  70     test_must_fail git cat-file blob $blob_1 > /dev/null &&
  71     test_must_fail git cat-file blob $blob_2 > /dev/null &&
  72     test_must_fail git cat-file blob $blob_3 > /dev/null'
  73
  74test_expect_success \
  75    '... but having a loose copy allows for full recovery' \
  76    'mv ${pack}.idx tmp &&
  77     git hash-object -t blob -w file_1 &&
  78     mv tmp ${pack}.idx &&
  79     git cat-file blob $blob_1 > /dev/null &&
  80     git cat-file blob $blob_2 > /dev/null &&
  81     git cat-file blob $blob_3 > /dev/null'
  82
  83test_expect_success \
  84    '... and loose copy of first delta allows for partial recovery' \
  85    'git prune-packed &&
  86     test_must_fail git cat-file blob $blob_2 > /dev/null &&
  87     mv ${pack}.idx tmp &&
  88     git hash-object -t blob -w file_2 &&
  89     mv tmp ${pack}.idx &&
  90     test_must_fail git cat-file blob $blob_1 > /dev/null &&
  91     git cat-file blob $blob_2 > /dev/null &&
  92     git cat-file blob $blob_3 > /dev/null'
  93
  94test_expect_success \
  95    'create corruption in data of first object' \
  96    'create_new_pack &&
  97     git prune-packed &&
  98     chmod +w ${pack}.pack &&
  99     perl -i.bak -pe "s/ base /abcdef/" ${pack}.pack &&
 100     test_must_fail git cat-file blob $blob_1 > /dev/null &&
 101     test_must_fail git cat-file blob $blob_2 > /dev/null &&
 102     test_must_fail git cat-file blob $blob_3 > /dev/null'
 103
 104test_expect_success \
 105    '... but having a loose copy allows for full recovery' \
 106    'mv ${pack}.idx tmp &&
 107     git hash-object -t blob -w file_1 &&
 108     mv tmp ${pack}.idx &&
 109     git cat-file blob $blob_1 > /dev/null &&
 110     git cat-file blob $blob_2 > /dev/null &&
 111     git cat-file blob $blob_3 > /dev/null'
 112
 113test_expect_success \
 114    '... and loose copy of second object allows for partial recovery' \
 115    'git prune-packed &&
 116     test_must_fail git cat-file blob $blob_2 > /dev/null &&
 117     mv ${pack}.idx tmp &&
 118     git hash-object -t blob -w file_2 &&
 119     mv tmp ${pack}.idx &&
 120     test_must_fail git cat-file blob $blob_1 > /dev/null &&
 121     git cat-file blob $blob_2 > /dev/null &&
 122     git cat-file blob $blob_3 > /dev/null'
 123
 124test_expect_success \
 125    'create corruption in header of first delta' \
 126    'create_new_pack &&
 127     git prune-packed &&
 128     do_corrupt_object $blob_2 0 < /dev/zero &&
 129     git cat-file blob $blob_1 > /dev/null &&
 130     test_must_fail git cat-file blob $blob_2 > /dev/null &&
 131     test_must_fail git cat-file blob $blob_3 > /dev/null'
 132
 133test_expect_success \
 134    '... but having a loose copy allows for full recovery' \
 135    'mv ${pack}.idx tmp &&
 136     git hash-object -t blob -w file_2 &&
 137     mv tmp ${pack}.idx &&
 138     git cat-file blob $blob_1 > /dev/null &&
 139     git cat-file blob $blob_2 > /dev/null &&
 140     git cat-file blob $blob_3 > /dev/null'
 141
 142test_expect_success \
 143    '... and then a repack "clears" the corruption' \
 144    'do_repack &&
 145     git prune-packed &&
 146     git verify-pack ${pack}.pack &&
 147     git cat-file blob $blob_1 > /dev/null &&
 148     git cat-file blob $blob_2 > /dev/null &&
 149     git cat-file blob $blob_3 > /dev/null'
 150
 151test_expect_success \
 152    'create corruption in data of first delta' \
 153    'create_new_pack &&
 154     git prune-packed &&
 155     chmod +w ${pack}.pack &&
 156     perl -i.bak -pe "s/ delta1 /abcdefgh/" ${pack}.pack &&
 157     git cat-file blob $blob_1 > /dev/null &&
 158     test_must_fail git cat-file blob $blob_2 > /dev/null &&
 159     test_must_fail git cat-file blob $blob_3 > /dev/null'
 160
 161test_expect_success \
 162    '... but having a loose copy allows for full recovery' \
 163    'mv ${pack}.idx tmp &&
 164     git hash-object -t blob -w file_2 &&
 165     mv tmp ${pack}.idx &&
 166     git cat-file blob $blob_1 > /dev/null &&
 167     git cat-file blob $blob_2 > /dev/null &&
 168     git cat-file blob $blob_3 > /dev/null'
 169
 170test_expect_success \
 171    '... and then a repack "clears" the corruption' \
 172    'do_repack &&
 173     git prune-packed &&
 174     git verify-pack ${pack}.pack &&
 175     git cat-file blob $blob_1 > /dev/null &&
 176     git cat-file blob $blob_2 > /dev/null &&
 177     git cat-file blob $blob_3 > /dev/null'
 178
 179test_expect_success \
 180    'corruption in delta base reference of first delta (OBJ_REF_DELTA)' \
 181    'create_new_pack &&
 182     git prune-packed &&
 183     do_corrupt_object $blob_2 2 < /dev/zero &&
 184     git cat-file blob $blob_1 > /dev/null &&
 185     test_must_fail git cat-file blob $blob_2 > /dev/null &&
 186     test_must_fail git cat-file blob $blob_3 > /dev/null'
 187
 188test_expect_success \
 189    '... but having a loose copy allows for full recovery' \
 190    'mv ${pack}.idx tmp &&
 191     git hash-object -t blob -w file_2 &&
 192     mv tmp ${pack}.idx &&
 193     git cat-file blob $blob_1 > /dev/null &&
 194     git cat-file blob $blob_2 > /dev/null &&
 195     git cat-file blob $blob_3 > /dev/null'
 196
 197test_expect_success \
 198    '... and then a repack "clears" the corruption' \
 199    'do_repack &&
 200     git prune-packed &&
 201     git verify-pack ${pack}.pack &&
 202     git cat-file blob $blob_1 > /dev/null &&
 203     git cat-file blob $blob_2 > /dev/null &&
 204     git cat-file blob $blob_3 > /dev/null'
 205
 206test_expect_success \
 207    'corruption #0 in delta base reference of first delta (OBJ_OFS_DELTA)' \
 208    'create_new_pack --delta-base-offset &&
 209     git prune-packed &&
 210     do_corrupt_object $blob_2 2 < /dev/zero &&
 211     git cat-file blob $blob_1 > /dev/null &&
 212     test_must_fail git cat-file blob $blob_2 > /dev/null &&
 213     test_must_fail git cat-file blob $blob_3 > /dev/null'
 214
 215test_expect_success \
 216    '... but having a loose copy allows for full recovery' \
 217    'mv ${pack}.idx tmp &&
 218     git hash-object -t blob -w file_2 &&
 219     mv tmp ${pack}.idx &&
 220     git cat-file blob $blob_1 > /dev/null &&
 221     git cat-file blob $blob_2 > /dev/null &&
 222     git cat-file blob $blob_3 > /dev/null'
 223
 224test_expect_success \
 225    '... and then a repack "clears" the corruption' \
 226    'do_repack --delta-base-offset &&
 227     git prune-packed &&
 228     git verify-pack ${pack}.pack &&
 229     git cat-file blob $blob_1 > /dev/null &&
 230     git cat-file blob $blob_2 > /dev/null &&
 231     git cat-file blob $blob_3 > /dev/null'
 232
 233test_expect_success \
 234    'corruption #1 in delta base reference of first delta (OBJ_OFS_DELTA)' \
 235    'create_new_pack --delta-base-offset &&
 236     git prune-packed &&
 237     printf "\001" | do_corrupt_object $blob_2 2 &&
 238     git cat-file blob $blob_1 > /dev/null &&
 239     test_must_fail git cat-file blob $blob_2 > /dev/null &&
 240     test_must_fail git cat-file blob $blob_3 > /dev/null'
 241
 242test_expect_success \
 243    '... but having a loose copy allows for full recovery' \
 244    'mv ${pack}.idx tmp &&
 245     git hash-object -t blob -w file_2 &&
 246     mv tmp ${pack}.idx &&
 247     git cat-file blob $blob_1 > /dev/null &&
 248     git cat-file blob $blob_2 > /dev/null &&
 249     git cat-file blob $blob_3 > /dev/null'
 250
 251test_expect_success \
 252    '... and then a repack "clears" the corruption' \
 253    'do_repack --delta-base-offset &&
 254     git prune-packed &&
 255     git verify-pack ${pack}.pack &&
 256     git cat-file blob $blob_1 > /dev/null &&
 257     git cat-file blob $blob_2 > /dev/null &&
 258     git cat-file blob $blob_3 > /dev/null'
 259
 260test_expect_success \
 261    '... and a redundant pack allows for full recovery too' \
 262    'do_corrupt_object $blob_2 2 < /dev/zero &&
 263     git cat-file blob $blob_1 > /dev/null &&
 264     test_must_fail git cat-file blob $blob_2 > /dev/null &&
 265     test_must_fail git cat-file blob $blob_3 > /dev/null &&
 266     mv ${pack}.idx tmp &&
 267     git hash-object -t blob -w file_1 &&
 268     git hash-object -t blob -w file_2 &&
 269     printf "$blob_1\n$blob_2\n" | git pack-objects .git/objects/pack/pack &&
 270     git prune-packed &&
 271     mv tmp ${pack}.idx &&
 272     git cat-file blob $blob_1 > /dev/null &&
 273     git cat-file blob $blob_2 > /dev/null &&
 274     git cat-file blob $blob_3 > /dev/null'
 275
 276test_done