t / t5303-pack-corruption-resilience.shon commit builtin-commit: use reduce_heads() only when appropriate (cf10f9f)
   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_corrupt_object() {
  45    ofs=`git show-index < ${pack}.idx | grep $1 | cut -f1 -d" "` &&
  46    ofs=$(($ofs + $2)) &&
  47    chmod +w ${pack}.pack &&
  48    dd if=/dev/zero of=${pack}.pack count=1 bs=1 conv=notrunc seek=$ofs &&
  49    test_must_fail git verify-pack ${pack}.pack
  50}
  51
  52test_expect_success \
  53    'initial setup validation' \
  54    'create_test_files &&
  55     create_new_pack &&
  56     git prune-packed &&
  57     git cat-file blob $blob_1 > /dev/null &&
  58     git cat-file blob $blob_2 > /dev/null &&
  59     git cat-file blob $blob_3 > /dev/null'
  60
  61test_expect_success \
  62    'create corruption in header of first object' \
  63    'do_corrupt_object $blob_1 0 &&
  64     test_must_fail git cat-file blob $blob_1 > /dev/null &&
  65     test_must_fail git cat-file blob $blob_2 > /dev/null &&
  66     test_must_fail git cat-file blob $blob_3 > /dev/null'
  67
  68test_expect_success \
  69    '... but having a loose copy allows for full recovery' \
  70    'mv ${pack}.idx tmp &&
  71     git hash-object -t blob -w file_1 &&
  72     mv tmp ${pack}.idx &&
  73     git cat-file blob $blob_1 > /dev/null &&
  74     git cat-file blob $blob_2 > /dev/null &&
  75     git cat-file blob $blob_3 > /dev/null'
  76
  77test_expect_success \
  78    '... and loose copy of first delta allows for partial recovery' \
  79    'git prune-packed &&
  80     test_must_fail git cat-file blob $blob_2 > /dev/null &&
  81     mv ${pack}.idx tmp &&
  82     git hash-object -t blob -w file_2 &&
  83     mv tmp ${pack}.idx &&
  84     test_must_fail git cat-file blob $blob_1 > /dev/null &&
  85     git cat-file blob $blob_2 > /dev/null &&
  86     git cat-file blob $blob_3 > /dev/null'
  87
  88test_expect_success \
  89    'create corruption in data of first object' \
  90    'create_new_pack &&
  91     git prune-packed &&
  92     chmod +w ${pack}.pack &&
  93     perl -i.bak -pe "s/ base /abcdef/" ${pack}.pack &&
  94     test_must_fail git cat-file blob $blob_1 > /dev/null &&
  95     test_must_fail git cat-file blob $blob_2 > /dev/null &&
  96     test_must_fail git cat-file blob $blob_3 > /dev/null'
  97
  98test_expect_success \
  99    '... but having a loose copy allows for full recovery' \
 100    'mv ${pack}.idx tmp &&
 101     git hash-object -t blob -w file_1 &&
 102     mv tmp ${pack}.idx &&
 103     git cat-file blob $blob_1 > /dev/null &&
 104     git cat-file blob $blob_2 > /dev/null &&
 105     git cat-file blob $blob_3 > /dev/null'
 106
 107test_expect_success \
 108    '... and loose copy of second object allows for partial recovery' \
 109    'git prune-packed &&
 110     test_must_fail git cat-file blob $blob_2 > /dev/null &&
 111     mv ${pack}.idx tmp &&
 112     git hash-object -t blob -w file_2 &&
 113     mv tmp ${pack}.idx &&
 114     test_must_fail git cat-file blob $blob_1 > /dev/null &&
 115     git cat-file blob $blob_2 > /dev/null &&
 116     git cat-file blob $blob_3 > /dev/null'
 117
 118test_expect_success \
 119    'create corruption in header of first delta' \
 120    'create_new_pack &&
 121     git prune-packed &&
 122     do_corrupt_object $blob_2 0 &&
 123     git cat-file blob $blob_1 > /dev/null &&
 124     test_must_fail git cat-file blob $blob_2 > /dev/null &&
 125     test_must_fail git cat-file blob $blob_3 > /dev/null'
 126
 127test_expect_success \
 128    '... but having a loose copy allows for full recovery' \
 129    'mv ${pack}.idx tmp &&
 130     git hash-object -t blob -w file_2 &&
 131     mv tmp ${pack}.idx &&
 132     git cat-file blob $blob_1 > /dev/null &&
 133     git cat-file blob $blob_2 > /dev/null &&
 134     git cat-file blob $blob_3 > /dev/null'
 135
 136test_expect_success \
 137    'create corruption in data of first delta' \
 138    'create_new_pack &&
 139     git prune-packed &&
 140     chmod +w ${pack}.pack &&
 141     perl -i.bak -pe "s/ delta1 /abcdefgh/" ${pack}.pack &&
 142     git cat-file blob $blob_1 > /dev/null &&
 143     test_must_fail git cat-file blob $blob_2 > /dev/null &&
 144     test_must_fail git cat-file blob $blob_3 > /dev/null'
 145
 146test_expect_success \
 147    '... but having a loose copy allows for full recovery' \
 148    'mv ${pack}.idx tmp &&
 149     git hash-object -t blob -w file_2 &&
 150     mv tmp ${pack}.idx &&
 151     git cat-file blob $blob_1 > /dev/null &&
 152     git cat-file blob $blob_2 > /dev/null &&
 153     git cat-file blob $blob_3 > /dev/null'
 154
 155test_expect_success \
 156    'corruption in delta base reference of first delta (OBJ_REF_DELTA)' \
 157    'create_new_pack &&
 158     git prune-packed &&
 159     do_corrupt_object $blob_2 2 &&
 160     git cat-file blob $blob_1 > /dev/null &&
 161     test_must_fail git cat-file blob $blob_2 > /dev/null &&
 162     test_must_fail git cat-file blob $blob_3 > /dev/null'
 163
 164test_expect_success \
 165    '... but having a loose copy allows for full recovery' \
 166    'mv ${pack}.idx tmp &&
 167     git hash-object -t blob -w file_2 &&
 168     mv tmp ${pack}.idx &&
 169     git cat-file blob $blob_1 > /dev/null &&
 170     git cat-file blob $blob_2 > /dev/null &&
 171     git cat-file blob $blob_3 > /dev/null'
 172
 173test_expect_success \
 174    'corruption in delta base reference of first delta (OBJ_OFS_DELTA)' \
 175    'create_new_pack --delta-base-offset &&
 176     git prune-packed &&
 177     do_corrupt_object $blob_2 2 &&
 178     git cat-file blob $blob_1 > /dev/null &&
 179     test_must_fail git cat-file blob $blob_2 > /dev/null &&
 180     test_must_fail git cat-file blob $blob_3 > /dev/null'
 181
 182test_expect_success \
 183    '... and a redundant pack allows for full recovery too' \
 184    'mv ${pack}.idx tmp &&
 185     git hash-object -t blob -w file_1 &&
 186     git hash-object -t blob -w file_2 &&
 187     printf "$blob_1\n$blob_2\n" | git pack-objects .git/objects/pack/pack &&
 188     git prune-packed &&
 189     mv tmp ${pack}.idx &&
 190     git cat-file blob $blob_1 > /dev/null &&
 191     git cat-file blob $blob_2 > /dev/null &&
 192     git cat-file blob $blob_3 > /dev/null'
 193
 194test_done