|
| 1 | +#!/bin/sh |
| 2 | +# |
| 3 | +# Copyright (c) 2008 Nicolas Pitre |
| 4 | +# |
| 5 | + |
| 6 | +test_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 | + |
| 21 | +create_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 | + |
| 32 | +create_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 | + |
| 44 | +do_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 | + |
| 52 | +test_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 | + |
| 61 | +test_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 | + |
| 68 | +test_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 | + |
| 77 | +test_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 | + |
| 88 | +test_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 -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 | + |
| 98 | +test_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 | + |
| 107 | +test_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 | + |
| 118 | +test_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 | + |
| 127 | +test_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 | + |
| 136 | +test_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 -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 | + |
| 146 | +test_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 | + |
| 155 | +test_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 | + |
| 164 | +test_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 | + |
| 173 | +test_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 | + |
| 182 | +test_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 | + |
| 194 | +test_done |
0 commit comments