Merge branch 'jc/rebase-orig-head'
[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_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.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
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.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
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