detached 98d36bf

budget_test.go RawHistoryFolder

1// SPDX-License-Identifier: AGPL-3.0-or-later
2
3package domain
4
5import (
6	"errors"
7	"testing"
8)
9
10func budgetID(t *testing.T, s string) ObjectID {
11	t.Helper()
12	id, err := ParseObjectID(s)
13	if err != nil {
14		t.Fatal(err)
15	}
16	return id
17}
18
19func TestValidateCommitObjects(t *testing.T) {
20	id := budgetID(t, "1111111111111111111111111111111111111111")
21	for _, tt := range []struct {
22		name string
23		ids  []ObjectID
24		max  int
25		want error
26	}{
27		{"empty", nil, 1, nil}, {"boundary", []ObjectID{id}, 1, nil},
28		{"too many", []ObjectID{id, id}, 1, ErrInvalid}, {"zero", []ObjectID{{}}, 1, ErrInvalidObjectID},
29	} {
30		t.Run(tt.name, func(t *testing.T) {
31			if err := ValidateCommitObjects(tt.ids, tt.max); !errors.Is(err, tt.want) {
32				t.Fatalf("got %v, want %v", err, tt.want)
33			}
34		})
35	}
36}
37
38func TestCommitObjectBudget(t *testing.T) {
39	id := budgetID(t, "1111111111111111111111111111111111111111")
40	for _, tt := range []struct {
41		name             string
42		commit           bool
43		size, total      int64
44		seen, take, stop bool
45	}{
46		{"non commit", false, 1, 0, false, false, false},
47		{"oversize", true, MaxCommitObjectBytes + 1, 0, false, false, false},
48		{"exact object", true, MaxCommitObjectBytes, 0, false, true, false},
49		{"exact total", true, 1, MaxCommitObjectsBytes - 1, false, true, false},
50		{"over total", true, 2, MaxCommitObjectsBytes - 1, false, false, true},
51		{"duplicate", true, 1, MaxCommitObjectsBytes, true, false, false},
52		{"negative", true, -1, 0, false, false, false},
53	} {
54		t.Run(tt.name, func(t *testing.T) {
55			b := CommitObjectBudget{total: tt.total}
56			if tt.seen {
57				b.seen = map[ObjectID]bool{id: true}
58			}
59			take, stop := b.Admit(id, tt.commit, tt.size)
60			if take != tt.take || stop != tt.stop {
61				t.Fatalf("got %v,%v", take, stop)
62			}
63			if take {
64				b.Charge(id, tt.size)
65				if !b.Seen(id) || b.total != tt.total+tt.size {
66					t.Fatal("charge not recorded")
67				}
68			}
69		})
70	}
71}
72
73func TestDiffBudgetWindow(t *testing.T) {
74	for _, tt := range []struct {
75		name           string
76		limits         DiffLimits
77		kept, from, to int
78		truncated      bool
79	}{
80		{"unlimited", DiffLimits{}, 5, 0, 5, false},
81		{"cap", DiffLimits{MaxFiles: 3}, 3, 0, 3, true},
82		{"window", DiffLimits{From: 1, To: 4}, 5, 1, 4, false},
83		{"clamped", DiffLimits{From: -1, To: 9, MaxFiles: 3}, 3, 0, 3, true},
84		{"past end", DiffLimits{From: 8}, 5, 8, 5, false},
85		{"reversed", DiffLimits{From: 4, To: 2}, 5, 4, 2, false},
86	} {
87		t.Run(tt.name, func(t *testing.T) {
88			b := NewDiffBudget(tt.limits)
89			k, f, to, tr := b.Window(5)
90			if k != tt.kept || f != tt.from || to != tt.to || tr != tt.truncated {
91				t.Fatalf("got %d,%d,%d,%v", k, f, to, tr)
92			}
93		})
94	}
95}
96
97func TestDiffBudgetHunks(t *testing.T) {
98	for _, tt := range []struct {
99		name            string
100		binary          bool
101		n, lines, bytes int
102		want            bool
103	}{
104		{"fits", false, 3, 3, 1, true}, {"binary", true, 3, 3, 1, false},
105		{"no changes", false, 0, 3, 1, false}, {"file limit", false, 4, 5, 1, false},
106		{"total lines", false, 3, 2, 1, false}, {"no bytes", false, 1, 3, 0, false},
107	} {
108		t.Run(tt.name, func(t *testing.T) {
109			b := NewDiffBudget(DiffLimits{MaxFileLines: 3, MaxTotalLines: tt.lines, MaxTotalBytes: tt.bytes})
110			if got := b.WantsHunks(tt.binary, tt.n); got != tt.want {
111				t.Fatalf("got %v", got)
112			}
113		})
114	}
115}
116
117func TestDiffBudgetCharge(t *testing.T) {
118	for _, tt := range []struct {
119		name  string
120		bytes int
121		fits  bool
122	}{{"exact", 3, true}, {"over", 4, false}} {
123		t.Run(tt.name, func(t *testing.T) {
124			b := NewDiffBudget(DiffLimits{MaxFileLines: 2, MaxTotalLines: 1, MaxTotalBytes: 3})
125			before := b
126			if b.FileLines() != 1 {
127				t.Fatal("wrong file limit")
128			}
129			if b.ChargeLine(tt.bytes) != tt.fits {
130				t.Fatal("wrong charge result")
131			}
132			if b.ChargeLine(0) {
133				t.Fatal("line budget exceeded")
134			}
135			b = before
136			if !b.WantsHunks(false, 1) {
137				t.Fatal("discarded file consumed budget")
138			}
139		})
140	}
141}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 4

Tags 45

↑↓ moveenter openesc close