Merge branch 'rw/maint-typofix' into rw/typofix
[git] / t / t5303-pack-corruption-resilience.sh
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_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
50 do_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
58 test_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
67 test_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
74 test_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
83 test_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
94 test_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
104 test_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
113 test_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
124 test_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
133 test_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
142 test_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
151 test_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
161 test_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
170 test_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
179 test_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
188 test_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
197 test_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
206 test_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
215 test_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
224 test_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
233 test_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
242 test_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
251 test_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
260 test_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
276 test_done