]> git.ipfire.org Git - thirdparty/git.git/blob - t/t4216-log-bloom.sh
bloom/diff: properly short-circuit on max_changes
[thirdparty/git.git] / t / t4216-log-bloom.sh
1 #!/bin/sh
2
3 test_description='git log for a path with Bloom filters'
4 . ./test-lib.sh
5
6 GIT_TEST_COMMIT_GRAPH=0
7 GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS=0
8
9 test_expect_success 'setup test - repo, commits, commit graph, log outputs' '
10 git init &&
11 mkdir A A/B A/B/C &&
12 test_commit c1 A/file1 &&
13 test_commit c2 A/B/file2 &&
14 test_commit c3 A/B/C/file3 &&
15 test_commit c4 A/file1 &&
16 test_commit c5 A/B/file2 &&
17 test_commit c6 A/B/C/file3 &&
18 test_commit c7 A/file1 &&
19 test_commit c8 A/B/file2 &&
20 test_commit c9 A/B/C/file3 &&
21 test_commit c10 file_to_be_deleted &&
22 git checkout -b side HEAD~4 &&
23 test_commit side-1 file4 &&
24 git checkout master &&
25 git merge side &&
26 test_commit c11 file5 &&
27 mv file5 file5_renamed &&
28 git add file5_renamed &&
29 git commit -m "rename" &&
30 rm file_to_be_deleted &&
31 git add . &&
32 git commit -m "file removed" &&
33 git commit-graph write --reachable --changed-paths
34 '
35 graph_read_expect () {
36 NUM_CHUNKS=5
37 cat >expect <<- EOF
38 header: 43475048 1 1 $NUM_CHUNKS 0
39 num_commits: $1
40 chunks: oid_fanout oid_lookup commit_metadata bloom_indexes bloom_data
41 EOF
42 test-tool read-graph >actual &&
43 test_cmp expect actual
44 }
45
46 test_expect_success 'commit-graph write wrote out the bloom chunks' '
47 graph_read_expect 15
48 '
49
50 # Turn off any inherited trace2 settings for this test.
51 sane_unset GIT_TRACE2 GIT_TRACE2_PERF GIT_TRACE2_EVENT
52 sane_unset GIT_TRACE2_PERF_BRIEF
53 sane_unset GIT_TRACE2_CONFIG_PARAMS
54
55 setup () {
56 rm -f "$TRASH_DIRECTORY/trace.perf" &&
57 git -c core.commitGraph=false log --pretty="format:%s" $1 >log_wo_bloom &&
58 GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.perf" git -c core.commitGraph=true log --pretty="format:%s" $1 >log_w_bloom
59 }
60
61 test_bloom_filters_used () {
62 log_args=$1
63 bloom_trace_prefix="statistics:{\"filter_not_present\":${2:-0},\"maybe\""
64 setup "$log_args" &&
65 grep -q "$bloom_trace_prefix" "$TRASH_DIRECTORY/trace.perf" &&
66 test_cmp log_wo_bloom log_w_bloom &&
67 test_path_is_file "$TRASH_DIRECTORY/trace.perf"
68 }
69
70 test_bloom_filters_not_used () {
71 log_args=$1
72 setup "$log_args" &&
73 ! grep -q "statistics:{\"filter_not_present\":" "$TRASH_DIRECTORY/trace.perf" &&
74 test_cmp log_wo_bloom log_w_bloom
75 }
76
77 for path in A A/B A/B/C A/file1 A/B/file2 A/B/C/file3 file4 file5 file5_renamed file_to_be_deleted
78 do
79 for option in "" \
80 "--all" \
81 "--full-history" \
82 "--full-history --simplify-merges" \
83 "--simplify-merges" \
84 "--simplify-by-decoration" \
85 "--follow" \
86 "--first-parent" \
87 "--topo-order" \
88 "--date-order" \
89 "--author-date-order" \
90 "--ancestry-path side..master"
91 do
92 test_expect_success "git log option: $option for path: $path" '
93 test_bloom_filters_used "$option -- $path" &&
94 test_config commitgraph.readChangedPaths false &&
95 test_bloom_filters_not_used "$option -- $path"
96 '
97 done
98 done
99
100 test_expect_success 'git log -- folder works with and without the trailing slash' '
101 test_bloom_filters_used "-- A" &&
102 test_bloom_filters_used "-- A/"
103 '
104
105 test_expect_success 'git log for path that does not exist. ' '
106 test_bloom_filters_used "-- path_does_not_exist"
107 '
108
109 test_expect_success 'git log with --walk-reflogs does not use Bloom filters' '
110 test_bloom_filters_not_used "--walk-reflogs -- A"
111 '
112
113 test_expect_success 'git log -- multiple path specs does not use Bloom filters' '
114 test_bloom_filters_not_used "-- file4 A/file1"
115 '
116
117 test_expect_success 'git log -- "." pathspec at root does not use Bloom filters' '
118 test_bloom_filters_not_used "-- ."
119 '
120
121 test_expect_success 'git log with wildcard that resolves to a single path uses Bloom filters' '
122 test_bloom_filters_used "-- *4" &&
123 test_bloom_filters_used "-- *renamed"
124 '
125
126 test_expect_success 'git log with wildcard that resolves to a multiple paths does not uses Bloom filters' '
127 test_bloom_filters_not_used "-- *" &&
128 test_bloom_filters_not_used "-- file*"
129 '
130
131 test_expect_success 'setup - add commit-graph to the chain without Bloom filters' '
132 test_commit c14 A/anotherFile2 &&
133 test_commit c15 A/B/anotherFile2 &&
134 test_commit c16 A/B/C/anotherFile2 &&
135 git commit-graph write --reachable --split --no-changed-paths &&
136 test_line_count = 2 .git/objects/info/commit-graphs/commit-graph-chain
137 '
138
139 test_expect_success 'use Bloom filters even if the latest graph does not have Bloom filters' '
140 # Ensure that the number of empty filters is equal to the number of
141 # filters in the latest graph layer to prove that they are loaded (and
142 # ignored).
143 test_bloom_filters_used "-- A/B" 3
144 '
145
146 test_expect_success 'setup - add commit-graph to the chain with Bloom filters' '
147 test_commit c17 A/anotherFile3 &&
148 git commit-graph write --reachable --changed-paths --split &&
149 test_line_count = 3 .git/objects/info/commit-graphs/commit-graph-chain
150 '
151
152 test_bloom_filters_used_when_some_filters_are_missing () {
153 log_args=$1
154 bloom_trace_prefix="statistics:{\"filter_not_present\":3,\"maybe\":6,\"definitely_not\":8"
155 setup "$log_args" &&
156 grep -q "$bloom_trace_prefix" "$TRASH_DIRECTORY/trace.perf" &&
157 test_cmp log_wo_bloom log_w_bloom
158 }
159
160 test_expect_success 'Use Bloom filters if they exist in the latest but not all commit graphs in the chain.' '
161 test_bloom_filters_used_when_some_filters_are_missing "-- A/B"
162 '
163
164 test_expect_success 'persist filter settings' '
165 test_when_finished rm -rf .git/objects/info/commit-graph* &&
166 rm -rf .git/objects/info/commit-graph* &&
167 GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
168 GIT_TRACE2_EVENT_NESTING=5 \
169 GIT_TEST_BLOOM_SETTINGS_NUM_HASHES=9 \
170 GIT_TEST_BLOOM_SETTINGS_BITS_PER_ENTRY=15 \
171 git commit-graph write --reachable --changed-paths &&
172 grep "{\"hash_version\":1,\"num_hashes\":9,\"bits_per_entry\":15,\"max_changed_paths\":512" trace2.txt &&
173 GIT_TRACE2_EVENT="$(pwd)/trace2-auto.txt" \
174 GIT_TRACE2_EVENT_NESTING=5 \
175 git commit-graph write --reachable --changed-paths &&
176 grep "{\"hash_version\":1,\"num_hashes\":9,\"bits_per_entry\":15,\"max_changed_paths\":512" trace2-auto.txt
177 '
178
179 test_max_changed_paths () {
180 grep "\"max_changed_paths\":$1" $2
181 }
182
183 test_filter_computed () {
184 grep "\"key\":\"filter-computed\",\"value\":\"$1\"" $2
185 }
186
187 test_filter_trunc_large () {
188 grep "\"key\":\"filter-trunc-large\",\"value\":\"$1\"" $2
189 }
190
191 test_expect_success 'correctly report changes over limit' '
192 git init limits &&
193 (
194 cd limits &&
195 mkdir d &&
196 mkdir d/e &&
197
198 for i in $(test_seq 1 2)
199 do
200 printf $i >d/file$i.txt &&
201 printf $i >d/e/file$i.txt || return 1
202 done &&
203
204 mkdir mode &&
205 printf bash >mode/script.sh &&
206
207 mkdir foo &&
208 touch foo/bar &&
209 touch foo.txt &&
210
211 git add d foo foo.txt mode &&
212 git commit -m "files" &&
213
214 # Commit has 7 file and 4 directory adds
215 GIT_TEST_BLOOM_SETTINGS_MAX_CHANGED_PATHS=10 \
216 GIT_TRACE2_EVENT="$(pwd)/trace" \
217 git commit-graph write --reachable --changed-paths &&
218 test_max_changed_paths 10 trace &&
219 test_filter_computed 1 trace &&
220 test_filter_trunc_large 1 trace &&
221
222 for path in $(git ls-tree -r --name-only HEAD)
223 do
224 git -c commitGraph.readChangedPaths=false log \
225 -- $path >expect &&
226 git log -- $path >actual &&
227 test_cmp expect actual || return 1
228 done &&
229
230 # Make a variety of path changes
231 printf new1 >d/e/file1.txt &&
232 printf new2 >d/file2.txt &&
233 rm d/e/file2.txt &&
234 rm -r foo &&
235 printf text >foo &&
236 mkdir f &&
237 printf new1 >f/file1.txt &&
238
239 # including a mode-only change (counts as modified)
240 git update-index --chmod=+x mode/script.sh &&
241
242 git add foo d f &&
243 git commit -m "complicated" &&
244
245 # start from scratch and rebuild
246 rm -f .git/objects/info/commit-graph &&
247 GIT_TEST_BLOOM_SETTINGS_MAX_CHANGED_PATHS=10 \
248 GIT_TRACE2_EVENT="$(pwd)/trace-edit" \
249 git commit-graph write --reachable --changed-paths &&
250 test_max_changed_paths 10 trace-edit &&
251 test_filter_computed 2 trace-edit &&
252 test_filter_trunc_large 2 trace-edit &&
253
254 for path in $(git ls-tree -r --name-only HEAD)
255 do
256 git -c commitGraph.readChangedPaths=false log \
257 -- $path >expect &&
258 git log -- $path >actual &&
259 test_cmp expect actual || return 1
260 done &&
261
262 # start from scratch and rebuild
263 rm -f .git/objects/info/commit-graph &&
264 GIT_TEST_BLOOM_SETTINGS_MAX_CHANGED_PATHS=11 \
265 GIT_TRACE2_EVENT="$(pwd)/trace-update" \
266 git commit-graph write --reachable --changed-paths &&
267 test_max_changed_paths 11 trace-update &&
268 test_filter_computed 2 trace-update &&
269 test_filter_trunc_large 0 trace-update &&
270
271 for path in $(git ls-tree -r --name-only HEAD)
272 do
273 git -c commitGraph.readChangedPaths=false log \
274 -- $path >expect &&
275 git log -- $path >actual &&
276 test_cmp expect actual || return 1
277 done
278 )
279 '
280
281 test_done