git/t/t5316-pack-delta-depth.sh
Ævar Arnfjörð Bjarmason e75d2f7f73 revisions API: have release_revisions() release "filter"
Extend the the release_revisions() function so that it frees the
"filter" in the "struct rev_info". This in combination with a
preceding change to free "cmdline" means that we can mark another set
of tests as passing under "TEST_PASSES_SANITIZE_LEAK=true".

The "filter" member was added recently in ffaa137f64 (revision: put
object filter into struct rev_info, 2022-03-09), and this fixes leaks
intruded in the subsequent leak 7940941de1 (pack-objects: use
rev.filter when possible, 2022-03-09) and 105c6f14ad (bundle: parse
filter capability, 2022-03-09).

The "builtin/pack-objects.c" leak in 7940941de1 was effectively with
us already, but the variable was referred to by a "static" file-scoped
variable. The "bundle.c " leak in 105c6f14ad was newly introduced
with the new "filter" feature for bundles.

The "t5600-clone-fail-cleanup.sh" change here to add
"TEST_PASSES_SANITIZE_LEAK=true" is one of the cases where
run-command.c in not carrying the abort() exit code upwards would have
had that test passing before, but now it *actually* passes[1]. We
should fix the lack of 1=1 mapping of SANITIZE=leak testing to actual
leaks some other time, but it's an existing edge case, let's just mark
the really-passing test as passing for now.

1. https://lore.kernel.org/git/220303.86fsnz5o9w.gmgdl@evledraar.gmail.com/

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2022-04-13 23:56:09 -07:00

121 lines
3.7 KiB
Bash
Executable file

#!/bin/sh
test_description='pack-objects breaks long cross-pack delta chains'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# This mirrors a repeated push setup:
#
# 1. A client repeatedly modifies some files, makes a
# commit, and pushes the result. It does this N times
# before we get around to repacking.
#
# 2. Each push generates a thin pack with the new version of
# various objects. Let's consider some file in the root tree
# which is updated in each commit.
#
# When generating push number X, we feed commit X-1 (and
# thus blob X-1) as a preferred base. The resulting pack has
# blob X as a thin delta against blob X-1.
#
# On the receiving end, "index-pack --fix-thin" will
# complete the pack with a base copy of blob X-1.
#
# 3. In older versions of git, if we used the delta from
# pack X, then we'd always find blob X-1 as a base in the
# same pack (and generate a fresh delta).
#
# But with the pack mru, we jump from delta to delta
# following the traversal order:
#
# a. We grab blob X from pack X as a delta, putting it at
# the tip of our mru list.
#
# b. Eventually we move onto commit X-1. We need other
# objects which are only in pack X-1 (in the test code
# below, it's the containing tree). That puts pack X-1
# at the tip of our mru list.
#
# c. Eventually we look for blob X-1, and we find the
# version in pack X-1 (because it's the mru tip).
#
# Now we have blob X as a delta against X-1, which is a delta
# against X-2, and so forth.
#
# In the real world, these small pushes would get exploded by
# unpack-objects rather than "index-pack --fix-thin", but the
# same principle applies to larger pushes (they only need one
# repeatedly-modified file to generate the delta chain).
test_expect_success 'create series of packs' '
test-tool genrandom foo 4096 >content &&
prev= &&
for i in $(test_seq 1 10)
do
cat content >file &&
echo $i >>file &&
git add file &&
git commit -m $i &&
cur=$(git rev-parse HEAD^{tree}) &&
{
if test -n "$prev"
then
echo "-$prev"
fi &&
echo $cur &&
echo "$(git rev-parse :file) file"
} | git pack-objects --stdout >tmp &&
GIT_TRACE2_EVENT=$PWD/trace \
git index-pack -v --stdin --fix-thin <tmp || return 1 &&
grep -c region_enter.*progress trace >enter &&
grep -c region_leave.*progress trace >leave &&
test_cmp enter leave &&
prev=$cur
done
'
max_chain() {
git index-pack --verify-stat-only "$1" >output &&
perl -lne '
BEGIN { $len = 0 }
/chain length = (\d+)/ and $len = $1;
END { print $len }
' output
}
# Note that this whole setup is pretty reliant on the current
# packing heuristics. We double-check that our test case
# actually produces a long chain. If it doesn't, it should be
# adjusted (or scrapped if the heuristics have become too unreliable)
test_expect_success 'packing produces a long delta' '
# Use --window=0 to make sure we are seeing reused deltas,
# not computing a new long chain.
pack=$(git pack-objects --all --window=0 </dev/null pack) &&
echo 9 >expect &&
max_chain pack-$pack.pack >actual &&
test_cmp expect actual
'
test_expect_success '--depth limits depth' '
pack=$(git pack-objects --all --depth=5 </dev/null pack) &&
echo 5 >expect &&
max_chain pack-$pack.pack >actual &&
test_cmp expect actual
'
test_expect_success '--depth=0 disables deltas' '
pack=$(git pack-objects --all --depth=0 </dev/null pack) &&
echo 0 >expect &&
max_chain pack-$pack.pack >actual &&
test_cmp expect actual
'
test_expect_success 'negative depth disables deltas' '
pack=$(git pack-objects --all --depth=-1 </dev/null pack) &&
echo 0 >expect &&
max_chain pack-$pack.pack >actual &&
test_cmp expect actual
'
test_done