commit-graph: drop COMMIT_GRAPH_WRITE_CHECK_OIDS flag
[git] / t / t5318-commit-graph.sh
1 #!/bin/sh
2
3 test_description='commit graph'
4 . ./test-lib.sh
5
6 GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS=0
7
8 test_expect_success 'setup full repo' '
9         mkdir full &&
10         cd "$TRASH_DIRECTORY/full" &&
11         git init &&
12         git config core.commitGraph true &&
13         objdir=".git/objects" &&
14         test_oid_init
15 '
16
17 test_expect_success 'verify graph with no graph file' '
18         cd "$TRASH_DIRECTORY/full" &&
19         git commit-graph verify
20 '
21
22 test_expect_success 'write graph with no packs' '
23         cd "$TRASH_DIRECTORY/full" &&
24         git commit-graph write --object-dir $objdir &&
25         test_path_is_missing $objdir/info/commit-graph
26 '
27
28 test_expect_success 'exit with correct error on bad input to --stdin-packs' '
29         cd "$TRASH_DIRECTORY/full" &&
30         echo doesnotexist >in &&
31         test_expect_code 1 git commit-graph write --stdin-packs <in 2>stderr &&
32         test_i18ngrep "error adding pack" stderr
33 '
34
35 test_expect_success 'create commits and repack' '
36         cd "$TRASH_DIRECTORY/full" &&
37         for i in $(test_seq 3)
38         do
39                 test_commit $i &&
40                 git branch commits/$i
41         done &&
42         git repack
43 '
44
45 graph_git_two_modes() {
46         git -c core.commitGraph=true $1 >output
47         git -c core.commitGraph=false $1 >expect
48         test_cmp expect output
49 }
50
51 graph_git_behavior() {
52         MSG=$1
53         DIR=$2
54         BRANCH=$3
55         COMPARE=$4
56         test_expect_success "check normal git operations: $MSG" '
57                 cd "$TRASH_DIRECTORY/$DIR" &&
58                 graph_git_two_modes "log --oneline $BRANCH" &&
59                 graph_git_two_modes "log --topo-order $BRANCH" &&
60                 graph_git_two_modes "log --graph $COMPARE..$BRANCH" &&
61                 graph_git_two_modes "branch -vv" &&
62                 graph_git_two_modes "merge-base -a $BRANCH $COMPARE"
63         '
64 }
65
66 graph_git_behavior 'no graph' full commits/3 commits/1
67
68 graph_read_expect() {
69         OPTIONAL=""
70         NUM_CHUNKS=3
71         if test ! -z $2
72         then
73                 OPTIONAL=" $2"
74                 NUM_CHUNKS=$((3 + $(echo "$2" | wc -w)))
75         fi
76         cat >expect <<- EOF
77         header: 43475048 1 1 $NUM_CHUNKS 0
78         num_commits: $1
79         chunks: oid_fanout oid_lookup commit_metadata$OPTIONAL
80         EOF
81         test-tool read-graph >output &&
82         test_cmp expect output
83 }
84
85 test_expect_success 'exit with correct error on bad input to --stdin-commits' '
86         cd "$TRASH_DIRECTORY/full" &&
87         # invalid, non-hex OID
88         echo HEAD >in &&
89         test_expect_code 1 git commit-graph write --stdin-commits <in 2>stderr &&
90         test_i18ngrep "unexpected non-hex object ID: HEAD" stderr &&
91         # non-existent OID
92         echo $ZERO_OID >in &&
93         test_expect_code 1 git commit-graph write --stdin-commits <in 2>stderr &&
94         test_i18ngrep "invalid object" stderr &&
95         # valid commit and tree OID
96         git rev-parse HEAD HEAD^{tree} >in &&
97         git commit-graph write --stdin-commits <in &&
98         graph_read_expect 3
99 '
100
101 test_expect_success 'write graph' '
102         cd "$TRASH_DIRECTORY/full" &&
103         git commit-graph write &&
104         test_path_is_file $objdir/info/commit-graph &&
105         graph_read_expect "3"
106 '
107
108 graph_git_behavior 'graph exists' full commits/3 commits/1
109
110 test_expect_success 'Add more commits' '
111         cd "$TRASH_DIRECTORY/full" &&
112         git reset --hard commits/1 &&
113         for i in $(test_seq 4 5)
114         do
115                 test_commit $i &&
116                 git branch commits/$i
117         done &&
118         git reset --hard commits/2 &&
119         for i in $(test_seq 6 7)
120         do
121                 test_commit $i &&
122                 git branch commits/$i
123         done &&
124         git reset --hard commits/2 &&
125         git merge commits/4 &&
126         git branch merge/1 &&
127         git reset --hard commits/4 &&
128         git merge commits/6 &&
129         git branch merge/2 &&
130         git reset --hard commits/3 &&
131         git merge commits/5 commits/7 &&
132         git branch merge/3 &&
133         git repack
134 '
135
136 test_expect_success 'commit-graph write progress off for redirected stderr' '
137         cd "$TRASH_DIRECTORY/full" &&
138         git commit-graph write 2>err &&
139         test_line_count = 0 err
140 '
141
142 test_expect_success 'commit-graph write force progress on for stderr' '
143         cd "$TRASH_DIRECTORY/full" &&
144         GIT_PROGRESS_DELAY=0 git commit-graph write --progress 2>err &&
145         test_file_not_empty err
146 '
147
148 test_expect_success 'commit-graph write with the --no-progress option' '
149         cd "$TRASH_DIRECTORY/full" &&
150         git commit-graph write --no-progress 2>err &&
151         test_line_count = 0 err
152 '
153
154 test_expect_success 'commit-graph verify progress off for redirected stderr' '
155         cd "$TRASH_DIRECTORY/full" &&
156         git commit-graph verify 2>err &&
157         test_line_count = 0 err
158 '
159
160 test_expect_success 'commit-graph verify force progress on for stderr' '
161         cd "$TRASH_DIRECTORY/full" &&
162         GIT_PROGRESS_DELAY=0 git commit-graph verify --progress 2>err &&
163         test_file_not_empty err
164 '
165
166 test_expect_success 'commit-graph verify with the --no-progress option' '
167         cd "$TRASH_DIRECTORY/full" &&
168         git commit-graph verify --no-progress 2>err &&
169         test_line_count = 0 err
170 '
171
172 # Current graph structure:
173 #
174 #   __M3___
175 #  /   |   \
176 # 3 M1 5 M2 7
177 # |/  \|/  \|
178 # 2    4    6
179 # |___/____/
180 # 1
181
182 test_expect_success 'write graph with merges' '
183         cd "$TRASH_DIRECTORY/full" &&
184         git commit-graph write &&
185         test_path_is_file $objdir/info/commit-graph &&
186         graph_read_expect "10" "extra_edges"
187 '
188
189 graph_git_behavior 'merge 1 vs 2' full merge/1 merge/2
190 graph_git_behavior 'merge 1 vs 3' full merge/1 merge/3
191 graph_git_behavior 'merge 2 vs 3' full merge/2 merge/3
192
193 test_expect_success 'Add one more commit' '
194         cd "$TRASH_DIRECTORY/full" &&
195         test_commit 8 &&
196         git branch commits/8 &&
197         ls $objdir/pack | grep idx >existing-idx &&
198         git repack &&
199         ls $objdir/pack| grep idx | grep -v -f existing-idx >new-idx
200 '
201
202 # Current graph structure:
203 #
204 #      8
205 #      |
206 #   __M3___
207 #  /   |   \
208 # 3 M1 5 M2 7
209 # |/  \|/  \|
210 # 2    4    6
211 # |___/____/
212 # 1
213
214 graph_git_behavior 'mixed mode, commit 8 vs merge 1' full commits/8 merge/1
215 graph_git_behavior 'mixed mode, commit 8 vs merge 2' full commits/8 merge/2
216
217 test_expect_success 'write graph with new commit' '
218         cd "$TRASH_DIRECTORY/full" &&
219         git commit-graph write &&
220         test_path_is_file $objdir/info/commit-graph &&
221         graph_read_expect "11" "extra_edges"
222 '
223
224 graph_git_behavior 'full graph, commit 8 vs merge 1' full commits/8 merge/1
225 graph_git_behavior 'full graph, commit 8 vs merge 2' full commits/8 merge/2
226
227 test_expect_success 'write graph with nothing new' '
228         cd "$TRASH_DIRECTORY/full" &&
229         git commit-graph write &&
230         test_path_is_file $objdir/info/commit-graph &&
231         graph_read_expect "11" "extra_edges"
232 '
233
234 graph_git_behavior 'cleared graph, commit 8 vs merge 1' full commits/8 merge/1
235 graph_git_behavior 'cleared graph, commit 8 vs merge 2' full commits/8 merge/2
236
237 test_expect_success 'build graph from latest pack with closure' '
238         cd "$TRASH_DIRECTORY/full" &&
239         cat new-idx | git commit-graph write --stdin-packs &&
240         test_path_is_file $objdir/info/commit-graph &&
241         graph_read_expect "9" "extra_edges"
242 '
243
244 graph_git_behavior 'graph from pack, commit 8 vs merge 1' full commits/8 merge/1
245 graph_git_behavior 'graph from pack, commit 8 vs merge 2' full commits/8 merge/2
246
247 test_expect_success 'build graph from commits with closure' '
248         cd "$TRASH_DIRECTORY/full" &&
249         git tag -a -m "merge" tag/merge merge/2 &&
250         git rev-parse tag/merge >commits-in &&
251         git rev-parse merge/1 >>commits-in &&
252         cat commits-in | git commit-graph write --stdin-commits &&
253         test_path_is_file $objdir/info/commit-graph &&
254         graph_read_expect "6"
255 '
256
257 graph_git_behavior 'graph from commits, commit 8 vs merge 1' full commits/8 merge/1
258 graph_git_behavior 'graph from commits, commit 8 vs merge 2' full commits/8 merge/2
259
260 test_expect_success 'build graph from commits with append' '
261         cd "$TRASH_DIRECTORY/full" &&
262         git rev-parse merge/3 | git commit-graph write --stdin-commits --append &&
263         test_path_is_file $objdir/info/commit-graph &&
264         graph_read_expect "10" "extra_edges"
265 '
266
267 graph_git_behavior 'append graph, commit 8 vs merge 1' full commits/8 merge/1
268 graph_git_behavior 'append graph, commit 8 vs merge 2' full commits/8 merge/2
269
270 test_expect_success 'build graph using --reachable' '
271         cd "$TRASH_DIRECTORY/full" &&
272         git commit-graph write --reachable &&
273         test_path_is_file $objdir/info/commit-graph &&
274         graph_read_expect "11" "extra_edges"
275 '
276
277 graph_git_behavior 'append graph, commit 8 vs merge 1' full commits/8 merge/1
278 graph_git_behavior 'append graph, commit 8 vs merge 2' full commits/8 merge/2
279
280 test_expect_success 'setup bare repo' '
281         cd "$TRASH_DIRECTORY" &&
282         git clone --bare --no-local full bare &&
283         cd bare &&
284         git config core.commitGraph true &&
285         baredir="./objects"
286 '
287
288 graph_git_behavior 'bare repo, commit 8 vs merge 1' bare commits/8 merge/1
289 graph_git_behavior 'bare repo, commit 8 vs merge 2' bare commits/8 merge/2
290
291 test_expect_success 'write graph in bare repo' '
292         cd "$TRASH_DIRECTORY/bare" &&
293         git commit-graph write &&
294         test_path_is_file $baredir/info/commit-graph &&
295         graph_read_expect "11" "extra_edges"
296 '
297
298 graph_git_behavior 'bare repo with graph, commit 8 vs merge 1' bare commits/8 merge/1
299 graph_git_behavior 'bare repo with graph, commit 8 vs merge 2' bare commits/8 merge/2
300
301 test_expect_success 'perform fast-forward merge in full repo' '
302         cd "$TRASH_DIRECTORY/full" &&
303         git checkout -b merge-5-to-8 commits/5 &&
304         git merge commits/8 &&
305         git show-ref -s merge-5-to-8 >output &&
306         git show-ref -s commits/8 >expect &&
307         test_cmp expect output
308 '
309
310 test_expect_success 'check that gc computes commit-graph' '
311         cd "$TRASH_DIRECTORY/full" &&
312         git commit --allow-empty -m "blank" &&
313         git commit-graph write --reachable &&
314         cp $objdir/info/commit-graph commit-graph-before-gc &&
315         git reset --hard HEAD~1 &&
316         git config gc.writeCommitGraph true &&
317         git gc &&
318         cp $objdir/info/commit-graph commit-graph-after-gc &&
319         ! test_cmp_bin commit-graph-before-gc commit-graph-after-gc &&
320         git commit-graph write --reachable &&
321         test_cmp_bin commit-graph-after-gc $objdir/info/commit-graph
322 '
323
324 test_expect_success 'replace-objects invalidates commit-graph' '
325         cd "$TRASH_DIRECTORY" &&
326         test_when_finished rm -rf replace &&
327         git clone full replace &&
328         (
329                 cd replace &&
330                 git commit-graph write --reachable &&
331                 test_path_is_file .git/objects/info/commit-graph &&
332                 git replace HEAD~1 HEAD~2 &&
333                 git -c core.commitGraph=false log >expect &&
334                 git -c core.commitGraph=true log >actual &&
335                 test_cmp expect actual &&
336                 git commit-graph write --reachable &&
337                 git -c core.commitGraph=false --no-replace-objects log >expect &&
338                 git -c core.commitGraph=true --no-replace-objects log >actual &&
339                 test_cmp expect actual &&
340                 rm -rf .git/objects/info/commit-graph &&
341                 git commit-graph write --reachable &&
342                 test_path_is_file .git/objects/info/commit-graph
343         )
344 '
345
346 test_expect_success 'commit grafts invalidate commit-graph' '
347         cd "$TRASH_DIRECTORY" &&
348         test_when_finished rm -rf graft &&
349         git clone full graft &&
350         (
351                 cd graft &&
352                 git commit-graph write --reachable &&
353                 test_path_is_file .git/objects/info/commit-graph &&
354                 H1=$(git rev-parse --verify HEAD~1) &&
355                 H3=$(git rev-parse --verify HEAD~3) &&
356                 echo "$H1 $H3" >.git/info/grafts &&
357                 git -c core.commitGraph=false log >expect &&
358                 git -c core.commitGraph=true log >actual &&
359                 test_cmp expect actual &&
360                 git commit-graph write --reachable &&
361                 git -c core.commitGraph=false --no-replace-objects log >expect &&
362                 git -c core.commitGraph=true --no-replace-objects log >actual &&
363                 test_cmp expect actual &&
364                 rm -rf .git/objects/info/commit-graph &&
365                 git commit-graph write --reachable &&
366                 test_path_is_missing .git/objects/info/commit-graph
367         )
368 '
369
370 test_expect_success 'replace-objects invalidates commit-graph' '
371         cd "$TRASH_DIRECTORY" &&
372         test_when_finished rm -rf shallow &&
373         git clone --depth 2 "file://$TRASH_DIRECTORY/full" shallow &&
374         (
375                 cd shallow &&
376                 git commit-graph write --reachable &&
377                 test_path_is_missing .git/objects/info/commit-graph &&
378                 git fetch origin --unshallow &&
379                 git commit-graph write --reachable &&
380                 test_path_is_file .git/objects/info/commit-graph
381         )
382 '
383
384 # the verify tests below expect the commit-graph to contain
385 # exactly the commits reachable from the commits/8 branch.
386 # If the file changes the set of commits in the list, then the
387 # offsets into the binary file will result in different edits
388 # and the tests will likely break.
389
390 test_expect_success 'git commit-graph verify' '
391         cd "$TRASH_DIRECTORY/full" &&
392         git rev-parse commits/8 | git commit-graph write --stdin-commits &&
393         git commit-graph verify >output
394 '
395
396 NUM_COMMITS=9
397 NUM_OCTOPUS_EDGES=2
398 HASH_LEN="$(test_oid rawsz)"
399 GRAPH_BYTE_VERSION=4
400 GRAPH_BYTE_HASH=5
401 GRAPH_BYTE_CHUNK_COUNT=6
402 GRAPH_CHUNK_LOOKUP_OFFSET=8
403 GRAPH_CHUNK_LOOKUP_WIDTH=12
404 GRAPH_CHUNK_LOOKUP_ROWS=5
405 GRAPH_BYTE_OID_FANOUT_ID=$GRAPH_CHUNK_LOOKUP_OFFSET
406 GRAPH_BYTE_OID_LOOKUP_ID=$(($GRAPH_CHUNK_LOOKUP_OFFSET + \
407                             1 * $GRAPH_CHUNK_LOOKUP_WIDTH))
408 GRAPH_BYTE_COMMIT_DATA_ID=$(($GRAPH_CHUNK_LOOKUP_OFFSET + \
409                              2 * $GRAPH_CHUNK_LOOKUP_WIDTH))
410 GRAPH_FANOUT_OFFSET=$(($GRAPH_CHUNK_LOOKUP_OFFSET + \
411                        $GRAPH_CHUNK_LOOKUP_WIDTH * $GRAPH_CHUNK_LOOKUP_ROWS))
412 GRAPH_BYTE_FANOUT1=$(($GRAPH_FANOUT_OFFSET + 4 * 4))
413 GRAPH_BYTE_FANOUT2=$(($GRAPH_FANOUT_OFFSET + 4 * 255))
414 GRAPH_OID_LOOKUP_OFFSET=$(($GRAPH_FANOUT_OFFSET + 4 * 256))
415 GRAPH_BYTE_OID_LOOKUP_ORDER=$(($GRAPH_OID_LOOKUP_OFFSET + $HASH_LEN * 8))
416 GRAPH_BYTE_OID_LOOKUP_MISSING=$(($GRAPH_OID_LOOKUP_OFFSET + $HASH_LEN * 4 + 10))
417 GRAPH_COMMIT_DATA_OFFSET=$(($GRAPH_OID_LOOKUP_OFFSET + $HASH_LEN * $NUM_COMMITS))
418 GRAPH_BYTE_COMMIT_TREE=$GRAPH_COMMIT_DATA_OFFSET
419 GRAPH_BYTE_COMMIT_PARENT=$(($GRAPH_COMMIT_DATA_OFFSET + $HASH_LEN))
420 GRAPH_BYTE_COMMIT_EXTRA_PARENT=$(($GRAPH_COMMIT_DATA_OFFSET + $HASH_LEN + 4))
421 GRAPH_BYTE_COMMIT_WRONG_PARENT=$(($GRAPH_COMMIT_DATA_OFFSET + $HASH_LEN + 3))
422 GRAPH_BYTE_COMMIT_GENERATION=$(($GRAPH_COMMIT_DATA_OFFSET + $HASH_LEN + 11))
423 GRAPH_BYTE_COMMIT_DATE=$(($GRAPH_COMMIT_DATA_OFFSET + $HASH_LEN + 12))
424 GRAPH_COMMIT_DATA_WIDTH=$(($HASH_LEN + 16))
425 GRAPH_OCTOPUS_DATA_OFFSET=$(($GRAPH_COMMIT_DATA_OFFSET + \
426                              $GRAPH_COMMIT_DATA_WIDTH * $NUM_COMMITS))
427 GRAPH_BYTE_OCTOPUS=$(($GRAPH_OCTOPUS_DATA_OFFSET + 4))
428 GRAPH_BYTE_FOOTER=$(($GRAPH_OCTOPUS_DATA_OFFSET + 4 * $NUM_OCTOPUS_EDGES))
429
430 corrupt_graph_setup() {
431         cd "$TRASH_DIRECTORY/full" &&
432         test_when_finished mv commit-graph-backup $objdir/info/commit-graph &&
433         cp $objdir/info/commit-graph commit-graph-backup
434 }
435
436 corrupt_graph_verify() {
437         grepstr=$1
438         test_must_fail git commit-graph verify 2>test_err &&
439         grep -v "^+" test_err >err &&
440         test_i18ngrep "$grepstr" err &&
441         if test "$2" != "no-copy"
442         then
443                 cp $objdir/info/commit-graph commit-graph-pre-write-test
444         fi &&
445         git status --short &&
446         GIT_TEST_COMMIT_GRAPH_DIE_ON_LOAD=true git commit-graph write &&
447         git commit-graph verify
448 }
449
450 # usage: corrupt_graph_and_verify <position> <data> <string> [<zero_pos>]
451 # Manipulates the commit-graph file at the position
452 # by inserting the data, optionally zeroing the file
453 # starting at <zero_pos>, then runs 'git commit-graph verify'
454 # and places the output in the file 'err'. Test 'err' for
455 # the given string.
456 corrupt_graph_and_verify() {
457         pos=$1
458         data="${2:-\0}"
459         grepstr=$3
460         corrupt_graph_setup &&
461         orig_size=$(wc -c < $objdir/info/commit-graph) &&
462         zero_pos=${4:-${orig_size}} &&
463         printf "$data" | dd of="$objdir/info/commit-graph" bs=1 seek="$pos" conv=notrunc &&
464         dd of="$objdir/info/commit-graph" bs=1 seek="$zero_pos" if=/dev/null &&
465         generate_zero_bytes $(($orig_size - $zero_pos)) >>"$objdir/info/commit-graph" &&
466         corrupt_graph_verify "$grepstr"
467
468 }
469
470 test_expect_success POSIXPERM,SANITY 'detect permission problem' '
471         corrupt_graph_setup &&
472         chmod 000 $objdir/info/commit-graph &&
473         corrupt_graph_verify "Could not open" "no-copy"
474 '
475
476 test_expect_success 'detect too small' '
477         corrupt_graph_setup &&
478         echo "a small graph" >$objdir/info/commit-graph &&
479         corrupt_graph_verify "too small"
480 '
481
482 test_expect_success 'detect bad signature' '
483         corrupt_graph_and_verify 0 "\0" \
484                 "graph signature"
485 '
486
487 test_expect_success 'detect bad version' '
488         corrupt_graph_and_verify $GRAPH_BYTE_VERSION "\02" \
489                 "graph version"
490 '
491
492 test_expect_success 'detect bad hash version' '
493         corrupt_graph_and_verify $GRAPH_BYTE_HASH "\03" \
494                 "hash version"
495 '
496
497 test_expect_success 'detect low chunk count' '
498         corrupt_graph_and_verify $GRAPH_BYTE_CHUNK_COUNT "\02" \
499                 "missing the .* chunk"
500 '
501
502 test_expect_success 'detect missing OID fanout chunk' '
503         corrupt_graph_and_verify $GRAPH_BYTE_OID_FANOUT_ID "\0" \
504                 "missing the OID Fanout chunk"
505 '
506
507 test_expect_success 'detect missing OID lookup chunk' '
508         corrupt_graph_and_verify $GRAPH_BYTE_OID_LOOKUP_ID "\0" \
509                 "missing the OID Lookup chunk"
510 '
511
512 test_expect_success 'detect missing commit data chunk' '
513         corrupt_graph_and_verify $GRAPH_BYTE_COMMIT_DATA_ID "\0" \
514                 "missing the Commit Data chunk"
515 '
516
517 test_expect_success 'detect incorrect fanout' '
518         corrupt_graph_and_verify $GRAPH_BYTE_FANOUT1 "\01" \
519                 "fanout value"
520 '
521
522 test_expect_success 'detect incorrect fanout final value' '
523         corrupt_graph_and_verify $GRAPH_BYTE_FANOUT2 "\01" \
524                 "fanout value"
525 '
526
527 test_expect_success 'detect incorrect OID order' '
528         corrupt_graph_and_verify $GRAPH_BYTE_OID_LOOKUP_ORDER "\01" \
529                 "incorrect OID order"
530 '
531
532 test_expect_success 'detect OID not in object database' '
533         corrupt_graph_and_verify $GRAPH_BYTE_OID_LOOKUP_MISSING "\01" \
534                 "from object database"
535 '
536
537 test_expect_success 'detect incorrect tree OID' '
538         corrupt_graph_and_verify $GRAPH_BYTE_COMMIT_TREE "\01" \
539                 "root tree OID for commit"
540 '
541
542 test_expect_success 'detect incorrect parent int-id' '
543         corrupt_graph_and_verify $GRAPH_BYTE_COMMIT_PARENT "\01" \
544                 "invalid parent"
545 '
546
547 test_expect_success 'detect extra parent int-id' '
548         corrupt_graph_and_verify $GRAPH_BYTE_COMMIT_EXTRA_PARENT "\00" \
549                 "is too long"
550 '
551
552 test_expect_success 'detect wrong parent' '
553         corrupt_graph_and_verify $GRAPH_BYTE_COMMIT_WRONG_PARENT "\01" \
554                 "commit-graph parent for"
555 '
556
557 test_expect_success 'detect incorrect generation number' '
558         corrupt_graph_and_verify $GRAPH_BYTE_COMMIT_GENERATION "\070" \
559                 "generation for commit"
560 '
561
562 test_expect_success 'detect incorrect generation number' '
563         corrupt_graph_and_verify $GRAPH_BYTE_COMMIT_GENERATION "\01" \
564                 "non-zero generation number"
565 '
566
567 test_expect_success 'detect incorrect commit date' '
568         corrupt_graph_and_verify $GRAPH_BYTE_COMMIT_DATE "\01" \
569                 "commit date"
570 '
571
572 test_expect_success 'detect incorrect parent for octopus merge' '
573         corrupt_graph_and_verify $GRAPH_BYTE_OCTOPUS "\01" \
574                 "invalid parent"
575 '
576
577 test_expect_success 'detect invalid checksum hash' '
578         corrupt_graph_and_verify $GRAPH_BYTE_FOOTER "\00" \
579                 "incorrect checksum"
580 '
581
582 test_expect_success 'detect incorrect chunk count' '
583         corrupt_graph_and_verify $GRAPH_BYTE_CHUNK_COUNT "\377" \
584                 "chunk lookup table entry missing" $GRAPH_CHUNK_LOOKUP_OFFSET
585 '
586
587 test_expect_success 'git fsck (checks commit-graph)' '
588         cd "$TRASH_DIRECTORY/full" &&
589         git fsck &&
590         corrupt_graph_and_verify $GRAPH_BYTE_FOOTER "\00" \
591                 "incorrect checksum" &&
592         cp commit-graph-pre-write-test $objdir/info/commit-graph &&
593         test_must_fail git fsck
594 '
595
596 test_expect_success 'setup non-the_repository tests' '
597         rm -rf repo &&
598         git init repo &&
599         test_commit -C repo one &&
600         test_commit -C repo two &&
601         git -C repo config core.commitGraph true &&
602         git -C repo rev-parse two | \
603                 git -C repo commit-graph write --stdin-commits
604 '
605
606 test_expect_success 'parse_commit_in_graph works for non-the_repository' '
607         test-tool repository parse_commit_in_graph \
608                 repo/.git repo "$(git -C repo rev-parse two)" >actual &&
609         {
610                 git -C repo log --pretty=format:"%ct " -1 &&
611                 git -C repo rev-parse one
612         } >expect &&
613         test_cmp expect actual &&
614
615         test-tool repository parse_commit_in_graph \
616                 repo/.git repo "$(git -C repo rev-parse one)" >actual &&
617         git -C repo log --pretty="%ct" -1 one >expect &&
618         test_cmp expect actual
619 '
620
621 test_expect_success 'get_commit_tree_in_graph works for non-the_repository' '
622         test-tool repository get_commit_tree_in_graph \
623                 repo/.git repo "$(git -C repo rev-parse two)" >actual &&
624         git -C repo rev-parse two^{tree} >expect &&
625         test_cmp expect actual &&
626
627         test-tool repository get_commit_tree_in_graph \
628                 repo/.git repo "$(git -C repo rev-parse one)" >actual &&
629         git -C repo rev-parse one^{tree} >expect &&
630         test_cmp expect actual
631 '
632
633 test_expect_success 'corrupt commit-graph write (broken parent)' '
634         rm -rf repo &&
635         git init repo &&
636         (
637                 cd repo &&
638                 empty="$(git mktree </dev/null)" &&
639                 cat >broken <<-EOF &&
640                 tree $empty
641                 parent $ZERO_OID
642                 author whatever <whatever@example.com> 1234 -0000
643                 committer whatever <whatever@example.com> 1234 -0000
644
645                 broken commit
646                 EOF
647                 broken="$(git hash-object -w -t commit --literally broken)" &&
648                 git commit-tree -p "$broken" -m "good commit" "$empty" >good &&
649                 test_must_fail git commit-graph write --stdin-commits \
650                         <good 2>test_err &&
651                 test_i18ngrep "unable to parse commit" test_err
652         )
653 '
654
655 test_expect_success 'corrupt commit-graph write (missing tree)' '
656         rm -rf repo &&
657         git init repo &&
658         (
659                 cd repo &&
660                 tree="$(git mktree </dev/null)" &&
661                 cat >broken <<-EOF &&
662                 parent $ZERO_OID
663                 author whatever <whatever@example.com> 1234 -0000
664                 committer whatever <whatever@example.com> 1234 -0000
665
666                 broken commit
667                 EOF
668                 broken="$(git hash-object -w -t commit --literally broken)" &&
669                 git commit-tree -p "$broken" -m "good" "$tree" >good &&
670                 test_must_fail git commit-graph write --stdin-commits \
671                         <good 2>test_err &&
672                 test_i18ngrep "unable to parse commit" test_err
673         )
674 '
675
676 test_done