1 #!/bin/sh
2 #
3 # Copyright (c) 2008 Nicolas Pitre
4 #
6 test_description='resilience to pack corruptions with redundant objects'
7 . ./test-lib.sh
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.
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 }
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 }
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 }
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'
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'
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'
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'
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.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'
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'
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'
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'
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'
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.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'
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'
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'
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'
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'
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'
194 test_done