Skip to content

Commit d8b4c5c

Browse files
committed
kvserver: test snapshot preparation
Epic: none Release note: none
1 parent fdac4fc commit d8b4c5c

File tree

3 files changed

+149
-0
lines changed

3 files changed

+149
-0
lines changed

pkg/kv/kvserver/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ go_test(
370370
"scatter_test.go",
371371
"scheduler_test.go",
372372
"single_key_test.go",
373+
"snapshot_apply_prepare_test.go",
373374
"split_delay_helper_test.go",
374375
"split_queue_test.go",
375376
"split_trigger_helper_test.go",
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
// Copyright 2025 The Cockroach Authors.
2+
//
3+
// Use of this software is governed by the CockroachDB Software License
4+
// included in the /LICENSE file.
5+
6+
package kvserver
7+
8+
import (
9+
"context"
10+
"path/filepath"
11+
"testing"
12+
13+
"github.com/cockroachdb/cockroach/pkg/keys"
14+
"github.com/cockroachdb/cockroach/pkg/kv/kvserver/concurrency/lock"
15+
"github.com/cockroachdb/cockroach/pkg/kv/kvserver/kvserverpb"
16+
"github.com/cockroachdb/cockroach/pkg/kv/kvserver/rditer"
17+
"github.com/cockroachdb/cockroach/pkg/kv/kvserver/stateloader"
18+
"github.com/cockroachdb/cockroach/pkg/raft/raftpb"
19+
"github.com/cockroachdb/cockroach/pkg/roachpb"
20+
"github.com/cockroachdb/cockroach/pkg/settings/cluster"
21+
"github.com/cockroachdb/cockroach/pkg/storage"
22+
"github.com/cockroachdb/cockroach/pkg/testutils/echotest"
23+
"github.com/cockroachdb/cockroach/pkg/testutils/storageutils"
24+
"github.com/cockroachdb/cockroach/pkg/util/hlc"
25+
"github.com/cockroachdb/cockroach/pkg/util/leaktest"
26+
"github.com/cockroachdb/cockroach/pkg/util/log"
27+
"github.com/cockroachdb/cockroach/pkg/util/uuid"
28+
"github.com/cockroachdb/redact"
29+
"github.com/stretchr/testify/require"
30+
)
31+
32+
// TestPrepareSnapApply tests the snapshot application code, which prepares a
33+
// set of SSTs to be ingested together with the snapshot SSTs. It this test, the
34+
// snapshot [a,k) subsumes replicas [a,b) and [b,z). Note that the key span
35+
// covered by the subsumed replicas is wider than the snapshot's.
36+
func TestPrepareSnapApply(t *testing.T) {
37+
defer leaktest.AfterTest(t)()
38+
defer log.Scope(t).Close(t)
39+
40+
var sb redact.StringBuilder
41+
writeSST := func(_ context.Context, data []byte) error {
42+
// TODO(pav-kv): range deletions are printed separately from point keys, and
43+
// this out-of-order output looks confusing. Improve it.
44+
return storageutils.ReportSSTEntries(&sb, "sst", data)
45+
}
46+
47+
desc := func(id roachpb.RangeID, start, end string) *roachpb.RangeDescriptor {
48+
return &roachpb.RangeDescriptor{
49+
RangeID: id,
50+
StartKey: roachpb.RKey(start),
51+
EndKey: roachpb.RKey(end),
52+
}
53+
}
54+
55+
id := storage.FullReplicaID{RangeID: 123, ReplicaID: 4}
56+
eng := storage.NewDefaultInMemForTesting()
57+
defer eng.Close()
58+
59+
descA := desc(101, "a", "b")
60+
descB := desc(102, "b", "z")
61+
createRangeData(t, eng, *descA)
62+
createRangeData(t, eng, *descB)
63+
64+
sl := stateloader.Make(id.RangeID)
65+
ctx := context.Background()
66+
require.NoError(t, sl.SetRaftReplicaID(ctx, eng, id.ReplicaID))
67+
for _, rID := range []roachpb.RangeID{101, 102} {
68+
require.NoError(t, stateloader.Make(rID).SetRaftReplicaID(ctx, eng, id.ReplicaID))
69+
}
70+
71+
in := prepareSnapApplyInput{
72+
id: id,
73+
st: cluster.MakeTestingClusterSettings(),
74+
todoEng: eng,
75+
sl: sl,
76+
writeSST: writeSST,
77+
78+
truncState: kvserverpb.RaftTruncatedState{Index: 100, Term: 20},
79+
hardState: raftpb.HardState{Term: 20, Commit: 100},
80+
desc: desc(id.RangeID, "a", "k"),
81+
subsumedDescs: []*roachpb.RangeDescriptor{descA, descB},
82+
}
83+
84+
clearedUnreplicatedSpan, clearedSubsumedSpans, err := prepareSnapApply(ctx, in)
85+
require.NoError(t, err)
86+
87+
sb.Printf(">> unrepl: %v\n", clearedUnreplicatedSpan)
88+
for _, span := range rditer.MakeReplicatedKeySpans(in.desc) {
89+
sb.Printf(">> repl: %v\n", span)
90+
}
91+
for _, span := range clearedSubsumedSpans {
92+
sb.Printf(">> subsumed: %v\n", span)
93+
}
94+
sb.Printf(">> excise: %v\n", in.desc.KeySpan().AsRawSpanWithNoLocals())
95+
96+
echotest.Require(t, sb.String(), filepath.Join("testdata", t.Name()+".txt"))
97+
}
98+
99+
func createRangeData(t *testing.T, eng storage.Engine, desc roachpb.RangeDescriptor) {
100+
ts := hlc.Timestamp{WallTime: 1}
101+
for _, k := range []roachpb.Key{
102+
keys.RangeDescriptorKey(desc.StartKey), // system
103+
desc.StartKey.AsRawKey(), // user
104+
roachpb.Key(desc.EndKey).Prevish(2), // user
105+
} {
106+
// Put something under the system or user key.
107+
require.NoError(t, eng.PutMVCC(
108+
storage.MVCCKey{Key: k, Timestamp: ts}, storage.MVCCValue{},
109+
))
110+
// Put something under the corresponding lock key.
111+
ek, _ := storage.LockTableKey{
112+
Key: k, Strength: lock.Intent, TxnUUID: uuid.UUID{},
113+
}.ToEngineKey(nil)
114+
require.NoError(t, eng.PutEngineKey(ek, nil))
115+
}
116+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
echo
2+
----
3+
>> sst:
4+
set: /Local/RangeID/123/u/RaftHardState/0,0 -> term:20 vote:0 commit:100 lead:0 lead_epoch:0
5+
set: /Local/RangeID/123/u/RaftReplicaID/0,0 -> replica_id:4
6+
set: /Local/RangeID/123/u/RaftTruncatedState/0,0 -> index:100 term:20
7+
rangedel: /Local/RangeID/123/{u""-v""}
8+
>> sst:
9+
set: /Local/RangeID/101/u/RangeTombstone/0,0 -> next_replica_id:2147483647
10+
rangedel: /Local/RangeID/101/{u/RaftReplicaID-v""}
11+
>> sst:
12+
set: /Local/RangeID/102/u/RangeTombstone/0,0 -> next_replica_id:2147483647
13+
rangedel: /Local/RangeID/102/{u/RaftReplicaID-v""}
14+
>> sst:
15+
del: /Local/Lock"y\xff"/0300000000000000000000000000000000 -> /<empty>
16+
>> sst:
17+
del: "y\xff"/0.000000001,0 -> /<empty>
18+
>> unrepl: /Local/RangeID/123/{u""-v""}
19+
>> repl: /Local/RangeID/123/{r""-s""}
20+
>> repl: /Local/Range"{a"-k"}
21+
>> repl: /Local/Lock/Local/Range"{a"-k"}
22+
>> repl: /Local/Lock"{a"-k"}
23+
>> repl: {a-k}
24+
>> subsumed: /Local/RangeID/101/{r""-s""}
25+
>> subsumed: /Local/RangeID/101/{u""-v""}
26+
>> subsumed: /Local/RangeID/102/{r""-s""}
27+
>> subsumed: /Local/RangeID/102/{u""-v""}
28+
>> subsumed: /Local/Range"{k"-z"}
29+
>> subsumed: /Local/Lock/Local/Range"{k"-z"}
30+
>> subsumed: /Local/Lock"{k"-z"}
31+
>> subsumed: {k-z}
32+
>> excise: {a-k}

0 commit comments

Comments
 (0)