aboutsummaryrefslogtreecommitdiffstats
path: root/t
diff options
context:
space:
mode:
Diffstat (limited to 't')
-rw-r--r--t/helper/test-bloom.c9
-rw-r--r--t/helper/test-read-graph.c65
-rwxr-xr-xt/t0095-bloom.sh8
-rwxr-xr-xt/t4216-log-bloom.sh325
4 files changed, 389 insertions, 18 deletions
diff --git a/t/helper/test-bloom.c b/t/helper/test-bloom.c
index f7f9b62002..97541daf71 100644
--- a/t/helper/test-bloom.c
+++ b/t/helper/test-bloom.c
@@ -51,6 +51,7 @@ static void get_bloom_filter_for_commit(const struct object_id *commit_oid)
static const char *bloom_usage = "\n"
" test-tool bloom get_murmur3 <string>\n"
+" test-tool bloom get_murmur3_seven_highbit\n"
" test-tool bloom generate_filter <string> [<string>...]\n"
" test-tool bloom get_filter_for_commit <commit-hex>\n";
@@ -65,7 +66,13 @@ int cmd__bloom(int argc, const char **argv)
uint32_t hashed;
if (argc < 3)
usage(bloom_usage);
- hashed = murmur3_seeded(0, argv[2], strlen(argv[2]));
+ hashed = murmur3_seeded_v2(0, argv[2], strlen(argv[2]));
+ printf("Murmur3 Hash with seed=0:0x%08x\n", hashed);
+ }
+
+ if (!strcmp(argv[1], "get_murmur3_seven_highbit")) {
+ uint32_t hashed;
+ hashed = murmur3_seeded_v2(0, "\x99\xaa\xbb\xcc\xdd\xee\xff", 7);
printf("Murmur3 Hash with seed=0:0x%08x\n", hashed);
}
diff --git a/t/helper/test-read-graph.c b/t/helper/test-read-graph.c
index d9e980d04c..9018c9f541 100644
--- a/t/helper/test-read-graph.c
+++ b/t/helper/test-read-graph.c
@@ -7,20 +7,8 @@
#include "bloom.h"
#include "setup.h"
-int cmd__read_graph(int argc UNUSED, const char **argv UNUSED)
+static void dump_graph_info(struct commit_graph *graph)
{
- struct commit_graph *graph = NULL;
- struct object_directory *odb;
-
- setup_git_directory();
- odb = the_repository->objects->odb;
-
- prepare_repo_settings(the_repository);
-
- graph = read_commit_graph_one(the_repository, odb);
- if (!graph)
- return 1;
-
printf("header: %08x %d %d %d %d\n",
ntohl(*(uint32_t*)graph->data),
*(unsigned char*)(graph->data + 4),
@@ -59,8 +47,57 @@ int cmd__read_graph(int argc UNUSED, const char **argv UNUSED)
if (graph->topo_levels)
printf(" topo_levels");
printf("\n");
+}
+
+static void dump_graph_bloom_filters(struct commit_graph *graph)
+{
+ uint32_t i;
+
+ for (i = 0; i < graph->num_commits + graph->num_commits_in_base; i++) {
+ struct bloom_filter filter = { 0 };
+ size_t j;
+
+ if (load_bloom_filter_from_graph(graph, &filter, i) < 0) {
+ fprintf(stderr, "missing Bloom filter for graph "
+ "position %"PRIu32"\n", i);
+ continue;
+ }
+
+ for (j = 0; j < filter.len; j++)
+ printf("%02x", filter.data[j]);
+ if (filter.len)
+ printf("\n");
+ }
+}
+
+int cmd__read_graph(int argc, const char **argv)
+{
+ struct commit_graph *graph = NULL;
+ struct object_directory *odb;
+ int ret = 0;
+
+ setup_git_directory();
+ odb = the_repository->objects->odb;
+
+ prepare_repo_settings(the_repository);
+
+ graph = read_commit_graph_one(the_repository, odb);
+ if (!graph) {
+ ret = 1;
+ goto done;
+ }
+
+ if (argc <= 1)
+ dump_graph_info(graph);
+ else if (!strcmp(argv[1], "bloom-filters"))
+ dump_graph_bloom_filters(graph);
+ else {
+ fprintf(stderr, "unknown sub-command: '%s'\n", argv[1]);
+ ret = 1;
+ }
+done:
UNLEAK(graph);
- return 0;
+ return ret;
}
diff --git a/t/t0095-bloom.sh b/t/t0095-bloom.sh
index b567383eb8..c8d84ab606 100755
--- a/t/t0095-bloom.sh
+++ b/t/t0095-bloom.sh
@@ -29,6 +29,14 @@ test_expect_success 'compute unseeded murmur3 hash for test string 2' '
test_cmp expect actual
'
+test_expect_success 'compute unseeded murmur3 hash for test string 3' '
+ cat >expect <<-\EOF &&
+ Murmur3 Hash with seed=0:0xa183ccfd
+ EOF
+ test-tool bloom get_murmur3_seven_highbit >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'compute bloom key for empty string' '
cat >expect <<-\EOF &&
Hashes:0x5615800c|0x5b966560|0x61174ab4|0x66983008|0x6c19155c|0x7199fab0|0x771ae004|
diff --git a/t/t4216-log-bloom.sh b/t/t4216-log-bloom.sh
index 2ba0324a69..3f163dc396 100755
--- a/t/t4216-log-bloom.sh
+++ b/t/t4216-log-bloom.sh
@@ -82,7 +82,23 @@ test_bloom_filters_used () {
test_bloom_filters_not_used () {
log_args=$1
setup "$log_args" &&
- ! grep -q "statistics:{\"filter_not_present\":" "$TRASH_DIRECTORY/trace.perf" &&
+
+ if grep -q "statistics:{\"filter_not_present\":" "$TRASH_DIRECTORY/trace.perf"
+ then
+ # if the Bloom filter system is initialized, ensure that no
+ # filters were used
+ data="statistics:{"
+ # unusable filters (e.g., those computed with a
+ # different value of commitGraph.changedPathsVersion)
+ # are counted in the filter_not_present bucket, so any
+ # value is OK there.
+ data="$data\"filter_not_present\":[0-9][0-9]*,"
+ data="$data\"maybe\":0,"
+ data="$data\"definitely_not\":0,"
+ data="$data\"false_positive\":0}"
+
+ grep -q "$data" "$TRASH_DIRECTORY/trace.perf"
+ fi &&
test_cmp log_wo_bloom log_w_bloom
}
@@ -163,7 +179,7 @@ test_expect_success 'setup - add commit-graph to the chain with Bloom filters' '
test_bloom_filters_used_when_some_filters_are_missing () {
log_args=$1
- bloom_trace_prefix="statistics:{\"filter_not_present\":3,\"maybe\":6,\"definitely_not\":9"
+ bloom_trace_prefix="statistics:{\"filter_not_present\":3,\"maybe\":6,\"definitely_not\":10"
setup "$log_args" &&
grep -q "$bloom_trace_prefix" "$TRASH_DIRECTORY/trace.perf" &&
test_cmp log_wo_bloom log_w_bloom
@@ -206,6 +222,10 @@ test_filter_trunc_large () {
grep "\"key\":\"filter-trunc-large\",\"value\":\"$1\"" $2
}
+test_filter_upgraded () {
+ grep "\"key\":\"filter-upgraded\",\"value\":\"$1\"" $2
+}
+
test_expect_success 'correctly report changes over limit' '
git init limits &&
(
@@ -405,8 +425,307 @@ test_expect_success 'Bloom generation backfills empty commits' '
)
'
+graph=.git/objects/info/commit-graph
+graphdir=.git/objects/info/commit-graphs
+chain=$graphdir/commit-graph-chain
+
+test_expect_success 'setup for mixed Bloom setting tests' '
+ repo=mixed-bloom-settings &&
+
+ git init $repo &&
+ for i in one two three
+ do
+ test_commit -C $repo $i file || return 1
+ done
+'
+
+test_expect_success 'ensure Bloom filters with incompatible settings are ignored' '
+ # Compute Bloom filters with "unusual" settings.
+ git -C $repo rev-parse one >in &&
+ GIT_TEST_BLOOM_SETTINGS_NUM_HASHES=3 git -C $repo commit-graph write \
+ --stdin-commits --changed-paths --split <in &&
+ layer=$(head -n 1 $repo/$chain) &&
+
+ # A commit-graph layer without Bloom filters "hides" the layers
+ # below ...
+ git -C $repo rev-parse two >in &&
+ git -C $repo commit-graph write --stdin-commits --no-changed-paths \
+ --split=no-merge <in &&
+
+ # Another commit-graph layer that has Bloom filters, but with
+ # standard settings, and is thus incompatible with the base
+ # layer written above.
+ git -C $repo rev-parse HEAD >in &&
+ git -C $repo commit-graph write --stdin-commits --changed-paths \
+ --split=no-merge <in &&
+
+ test_line_count = 3 $repo/$chain &&
+
+ # Ensure that incompatible Bloom filters are ignored.
+ git -C $repo -c core.commitGraph=false log --oneline --no-decorate -- file \
+ >expect 2>err &&
+ git -C $repo log --oneline --no-decorate -- file >actual 2>err &&
+ test_cmp expect actual &&
+ grep "disabling Bloom filters for commit-graph layer .$layer." err
+'
+
+test_expect_success 'merge graph layers with incompatible Bloom settings' '
+ # Ensure that incompatible Bloom filters are ignored when
+ # merging existing layers.
+ >trace2.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+ git -C $repo commit-graph write --reachable --changed-paths 2>err &&
+ grep "disabling Bloom filters for commit-graph layer .$layer." err &&
+ grep "{\"hash_version\":1,\"num_hashes\":7,\"bits_per_entry\":10,\"max_changed_paths\":512" trace2.txt &&
+
+ test_path_is_file $repo/$graph &&
+ test_dir_is_empty $repo/$graphdir &&
+
+ git -C $repo -c core.commitGraph=false log --oneline --no-decorate -- \
+ file >expect &&
+ trace_out="$(pwd)/trace.perf" &&
+ GIT_TRACE2_PERF="$trace_out" \
+ git -C $repo log --oneline --no-decorate -- file >actual 2>err &&
+
+ test_cmp expect actual &&
+ grep "statistics:{\"filter_not_present\":0," trace.perf &&
+ test_must_be_empty err
+'
+
+# chosen to be the same under all Unicode normalization forms
+CENT=$(printf "\302\242")
+
+test_expect_success 'ensure Bloom filter with incompatible versions are ignored' '
+ rm "$repo/$graph" &&
+
+ git -C $repo log --oneline --no-decorate -- $CENT >expect &&
+
+ # Compute v1 Bloom filters for commits at the bottom.
+ git -C $repo rev-parse HEAD^ >in &&
+ git -C $repo commit-graph write --stdin-commits --changed-paths \
+ --split <in &&
+
+ # Compute v2 Bloomfilters for the rest of the commits at the top.
+ git -C $repo rev-parse HEAD >in &&
+ git -C $repo -c commitGraph.changedPathsVersion=2 commit-graph write \
+ --stdin-commits --changed-paths --split=no-merge <in &&
+
+ test_line_count = 2 $repo/$chain &&
+
+ git -C $repo log --oneline --no-decorate -- $CENT >actual 2>err &&
+ test_cmp expect actual &&
+
+ layer="$(head -n 1 $repo/$chain)" &&
+ cat >expect.err <<-EOF &&
+ warning: disabling Bloom filters for commit-graph layer $SQ$layer$SQ due to incompatible settings
+ EOF
+ test_cmp expect.err err &&
+
+ # Merge the two layers with incompatible bloom filter versions,
+ # ensuring that the v2 filters are used.
+ >trace2.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+ git -C $repo -c commitGraph.changedPathsVersion=2 commit-graph write --reachable --changed-paths 2>err &&
+ grep "disabling Bloom filters for commit-graph layer .$layer." err &&
+ grep "{\"hash_version\":2,\"num_hashes\":7,\"bits_per_entry\":10,\"max_changed_paths\":512" trace2.txt
+'
+
+get_first_changed_path_filter () {
+ test-tool read-graph bloom-filters >filters.dat &&
+ head -n 1 filters.dat
+}
+
+test_expect_success 'set up repo with high bit path, version 1 changed-path' '
+ git init highbit1 &&
+ test_commit -C highbit1 c1 "$CENT" &&
+ git -C highbit1 commit-graph write --reachable --changed-paths
+'
+
+test_expect_success 'setup check value of version 1 changed-path' '
+ (
+ cd highbit1 &&
+ echo "52a9" >expect &&
+ get_first_changed_path_filter >actual
+ )
+'
+
+# expect will not match actual if char is unsigned by default. Write the test
+# in this way, so that a user running this test script can still see if the two
+# files match. (It will appear as an ordinary success if they match, and a skip
+# if not.)
+if test_cmp highbit1/expect highbit1/actual
+then
+ test_set_prereq SIGNED_CHAR_BY_DEFAULT
+fi
+test_expect_success SIGNED_CHAR_BY_DEFAULT 'check value of version 1 changed-path' '
+ # Only the prereq matters for this test.
+ true
+'
+
+test_expect_success 'setup make another commit' '
+ # "git log" does not use Bloom filters for root commits - see how, in
+ # revision.c, rev_compare_tree() (the only code path that eventually calls
+ # get_bloom_filter()) is only called by try_to_simplify_commit() when the commit
+ # has one parent. Therefore, make another commit so that we perform the tests on
+ # a non-root commit.
+ test_commit -C highbit1 anotherc1 "another$CENT"
+'
+
+test_expect_success 'version 1 changed-path used when version 1 requested' '
+ (
+ cd highbit1 &&
+ test_bloom_filters_used "-- another$CENT"
+ )
+'
+
+test_expect_success 'version 1 changed-path not used when version 2 requested' '
+ (
+ cd highbit1 &&
+ git config --add commitGraph.changedPathsVersion 2 &&
+ test_bloom_filters_not_used "-- another$CENT"
+ )
+'
+
+test_expect_success 'version 1 changed-path used when autodetect requested' '
+ (
+ cd highbit1 &&
+ git config --add commitGraph.changedPathsVersion -1 &&
+ test_bloom_filters_used "-- another$CENT"
+ )
+'
+
+test_expect_success 'when writing another commit graph, preserve existing version 1 of changed-path' '
+ test_commit -C highbit1 c1double "$CENT$CENT" &&
+ git -C highbit1 commit-graph write --reachable --changed-paths &&
+ (
+ cd highbit1 &&
+ git config --add commitGraph.changedPathsVersion -1 &&
+ echo "options: bloom(1,10,7) read_generation_data" >expect &&
+ test-tool read-graph >full &&
+ grep options full >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'set up repo with high bit path, version 2 changed-path' '
+ git init highbit2 &&
+ git -C highbit2 config --add commitGraph.changedPathsVersion 2 &&
+ test_commit -C highbit2 c2 "$CENT" &&
+ git -C highbit2 commit-graph write --reachable --changed-paths
+'
+
+test_expect_success 'check value of version 2 changed-path' '
+ (
+ cd highbit2 &&
+ echo "c01f" >expect &&
+ get_first_changed_path_filter >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'setup make another commit' '
+ # "git log" does not use Bloom filters for root commits - see how, in
+ # revision.c, rev_compare_tree() (the only code path that eventually calls
+ # get_bloom_filter()) is only called by try_to_simplify_commit() when the commit
+ # has one parent. Therefore, make another commit so that we perform the tests on
+ # a non-root commit.
+ test_commit -C highbit2 anotherc2 "another$CENT"
+'
+
+test_expect_success 'version 2 changed-path used when version 2 requested' '
+ (
+ cd highbit2 &&
+ test_bloom_filters_used "-- another$CENT"
+ )
+'
+
+test_expect_success 'version 2 changed-path not used when version 1 requested' '
+ (
+ cd highbit2 &&
+ git config --add commitGraph.changedPathsVersion 1 &&
+ test_bloom_filters_not_used "-- another$CENT"
+ )
+'
+
+test_expect_success 'version 2 changed-path used when autodetect requested' '
+ (
+ cd highbit2 &&
+ git config --add commitGraph.changedPathsVersion -1 &&
+ test_bloom_filters_used "-- another$CENT"
+ )
+'
+
+test_expect_success 'when writing another commit graph, preserve existing version 2 of changed-path' '
+ test_commit -C highbit2 c2double "$CENT$CENT" &&
+ git -C highbit2 commit-graph write --reachable --changed-paths &&
+ (
+ cd highbit2 &&
+ git config --add commitGraph.changedPathsVersion -1 &&
+ echo "options: bloom(2,10,7) read_generation_data" >expect &&
+ test-tool read-graph >full &&
+ grep options full >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'when writing commit graph, do not reuse changed-path of another version' '
+ git init doublewrite &&
+ test_commit -C doublewrite c "$CENT" &&
+
+ git -C doublewrite config --add commitGraph.changedPathsVersion 1 &&
+ >trace2.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+ git -C doublewrite commit-graph write --reachable --changed-paths &&
+ test_filter_computed 1 trace2.txt &&
+ test_filter_upgraded 0 trace2.txt &&
+
+ git -C doublewrite commit-graph write --reachable --changed-paths &&
+ for v in -2 3
+ do
+ git -C doublewrite config --add commitGraph.changedPathsVersion $v &&
+ git -C doublewrite commit-graph write --reachable --changed-paths 2>err &&
+ cat >expect <<-EOF &&
+ warning: attempting to write a commit-graph, but ${SQ}commitGraph.changedPathsVersion${SQ} ($v) is not supported
+ EOF
+ test_cmp expect err || return 1
+ done &&
+
+ git -C doublewrite config --add commitGraph.changedPathsVersion 2 &&
+ >trace2.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+ git -C doublewrite commit-graph write --reachable --changed-paths &&
+ test_filter_computed 1 trace2.txt &&
+ test_filter_upgraded 0 trace2.txt &&
+
+ (
+ cd doublewrite &&
+ echo "c01f" >expect &&
+ get_first_changed_path_filter >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'when writing commit graph, reuse changed-path of another version where possible' '
+ git init upgrade &&
+
+ test_commit -C upgrade base no-high-bits &&
+
+ git -C upgrade config --add commitGraph.changedPathsVersion 1 &&
+ >trace2.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+ git -C upgrade commit-graph write --reachable --changed-paths &&
+ test_filter_computed 1 trace2.txt &&
+ test_filter_upgraded 0 trace2.txt &&
+
+ git -C upgrade config --add commitGraph.changedPathsVersion 2 &&
+ >trace2.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+ git -C upgrade commit-graph write --reachable --changed-paths &&
+ test_filter_computed 0 trace2.txt &&
+ test_filter_upgraded 1 trace2.txt
+'
+
corrupt_graph () {
- graph=.git/objects/info/commit-graph &&
test_when_finished "rm -rf $graph" &&
git commit-graph write --reachable --changed-paths &&
corrupt_chunk_file $graph "$@"