v0.1.0 8b870d7

batch_test.go RawHistoryFolder

1// SPDX-License-Identifier: MIT
2
3package kv
4
5import (
6	"bytes"
7	"errors"
8	"strings"
9	"testing"
10)
11
12func TestBatchCopiesInputs(t *testing.T) {
13	var b Batch
14	key, val := []byte("key"), []byte("value")
15	b.Put(key, val)
16	b.Delete(key)
17	b.RequireAbsent(key)
18	b.RequireVersion(key, 3)
19	key[0], val[0] = 'X', 'X'
20	if got := b.ops[0]; string(got.key) != "key" || string(got.value) != "value" {
21		t.Fatalf("put aliases its inputs: %q=%q", got.key, got.value)
22	}
23	if got := b.ops[1]; string(got.key) != "key" {
24		t.Fatalf("delete aliases its key: %q", got.key)
25	}
26	for i, p := range b.pre {
27		if string(p.key) != "key" {
28			t.Fatalf("precondition %d aliases its key: %q", i, p.key)
29		}
30	}
31	if b.Len() != 4 {
32		t.Fatalf("Len = %d, want 4", b.Len())
33	}
34}
35
36func TestBatchErrors(t *testing.T) {
37	long := bytes.Repeat([]byte("k"), maxKeyLen+1)
38	cases := map[string]func(b *Batch){
39		"put empty":      func(b *Batch) { b.Put(nil, []byte("v")) },
40		"put long":       func(b *Batch) { b.Put(long, nil) },
41		"delete empty":   func(b *Batch) { b.Delete([]byte{}) },
42		"absent empty":   func(b *Batch) { b.RequireAbsent(nil) },
43		"version empty":  func(b *Batch) { b.RequireVersion(nil, 1) },
44		"version zero":   func(b *Batch) { b.RequireVersion([]byte("k"), 0) },
45		"after valid op": func(b *Batch) { b.Put([]byte("a"), nil); b.Put(nil, nil); b.Put([]byte("b"), nil) },
46	}
47	for name, fn := range cases {
48		t.Run(name, func(t *testing.T) {
49			var b Batch
50			fn(&b)
51			if !errors.Is(b.err, ErrInvalidKey) {
52				t.Fatalf("err = %v, want ErrInvalidKey", b.err)
53			}
54			b.Reset()
55			if b.err != nil || b.Len() != 0 || b.encodedSize() != 0 {
56				t.Fatalf("Reset left err=%v len=%d size=%d", b.err, b.Len(), b.encodedSize())
57			}
58		})
59	}
60
61	var b Batch
62	b.Put(bytes.Repeat([]byte("k"), maxKeyLen), nil) // exactly the limit
63	if b.err != nil {
64		t.Fatalf("64 KiB key rejected: %v", b.err)
65	}
66}
67
68func TestBatchEncodedSize(t *testing.T) {
69	var b Batch
70	if b.encodedSize() != 0 {
71		t.Fatal("empty batch has a payload")
72	}
73	b.RequireAbsent([]byte("k"))
74	if b.encodedSize() != 0 {
75		t.Fatal("precondition-only batch has a payload")
76	}
77	b.Put([]byte("k"), []byte(strings.Repeat("v", 200)))
78	b.Delete([]byte("kk"))
79	want := len(appendRecord(nil, 1, b.ops)) - recordFrame - recordHead
80	if got := b.encodedSize(); got != want {
81		t.Fatalf("payload = %d, encoded batch = %d", got, want)
82	}
83}

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 1

Tags 2

↑↓ moveenter openesc close