Skip to content

Commit 2a31327

Browse files
committed
test(kv): add FSM-level threading tests for SetApplyIndex → applier raftIdx
Closes the unit-test coverage gap claude's PR784 round-2 review identified: the applier-level regression tests (TestApplyBootstrap_PersistsRaftAppliedIndex) call ApplyBootstrap directly, bypassing the FSM. Without this commit, a future refactor that accidentally drops `f.pendingApplyIdx` from `applyEncryption`'s argument list (or reorders the SetApplyIndex / Apply sequence at the engine boundary) would not be caught at unit-test level — the full chain would still compile but the index would be silently truncated to zero. Two new tests pin the chain: - TestApply_Bootstrap_ThreadsRaftIdx — SetApplyIndex(184273) + Apply(0x04) → assert applier.lastBootstrapIdx == 184273 - TestApply_Rotation_ThreadsRaftIdx — same for the 0x05 rotation path Both use the existing fakeApplier (whose lastBootstrapIdx / lastRotationIdx fields were added in commit 487e21d) so no production code changed. go test -race ./kv/ — PASS golangci-lint run ./kv/ — 0 issues
1 parent 487e21d commit 2a31327

1 file changed

Lines changed: 68 additions & 0 deletions

File tree

kv/fsm_encryption_test.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,74 @@ func TestApply_Bootstrap_HappyPath(t *testing.T) {
125125
}
126126
}
127127

128+
// TestApply_Bootstrap_ThreadsRaftIdx pins the §9.1 plumbing chain
129+
// from raftengine.ApplyIndexAware through to the EncryptionApplier:
130+
// SetApplyIndex(N) on the FSM, then Apply(0x04 entry) — the
131+
// resulting ApplyBootstrap call MUST observe raftIdx=N.
132+
//
133+
// Without this test, a future refactor that accidentally drops
134+
// pendingApplyIdx from the applyEncryption argument list (or
135+
// reorders the SetApplyIndex / Apply sequence at the engine
136+
// boundary) would not be caught at unit-test level. The
137+
// applier-level regression test (TestApplyBootstrap_PersistsRaftAppliedIndex)
138+
// bypasses the FSM by calling ApplyBootstrap directly, so it
139+
// would not exercise this code path.
140+
func TestApply_Bootstrap_ThreadsRaftIdx(t *testing.T) {
141+
t.Parallel()
142+
applier := &fakeApplier{}
143+
f := newFSMWithFake(applier)
144+
145+
const wantIdx uint64 = 184273
146+
f.SetApplyIndex(wantIdx)
147+
148+
want := fsmwire.BootstrapPayload{
149+
StorageDEKID: 1,
150+
WrappedStorage: []byte("storage-w"),
151+
RaftDEKID: 2,
152+
WrappedRaft: []byte("raft-w"),
153+
BatchRegistry: []fsmwire.RegistrationPayload{{DEKID: 1, FullNodeID: 11, LocalEpoch: 1}},
154+
}
155+
wireBytes := append([]byte{fsmwire.OpBootstrap}, fsmwire.EncodeBootstrap(want)...)
156+
157+
if err := haltApplyOf(f.Apply(wireBytes)); err != nil {
158+
t.Fatalf("unexpected halt: %v", err)
159+
}
160+
if applier.lastBootstrapIdx != wantIdx {
161+
t.Fatalf("ApplyBootstrap observed raftIdx=%d, want %d (§9.1 threading chain dropped)",
162+
applier.lastBootstrapIdx, wantIdx)
163+
}
164+
}
165+
166+
// TestApply_Rotation_ThreadsRaftIdx is the rotation counterpart of
167+
// TestApply_Bootstrap_ThreadsRaftIdx: same plumbing chain through
168+
// the 0x05 dispatch.
169+
func TestApply_Rotation_ThreadsRaftIdx(t *testing.T) {
170+
t.Parallel()
171+
applier := &fakeApplier{}
172+
f := newFSMWithFake(applier)
173+
174+
const wantIdx uint64 = 184274
175+
f.SetApplyIndex(wantIdx)
176+
177+
want := fsmwire.RotationPayload{
178+
SubTag: fsmwire.RotateSubRotateDEK,
179+
DEKID: 42,
180+
Purpose: fsmwire.PurposeStorage,
181+
Wrapped: []byte("new-w"),
182+
ProposerRegistration: fsmwire.RegistrationPayload{
183+
DEKID: 42, FullNodeID: 99, LocalEpoch: 1,
184+
},
185+
}
186+
wireBytes := append([]byte{fsmwire.OpRotation}, fsmwire.EncodeRotation(want)...)
187+
188+
if err := haltApplyOf(f.Apply(wireBytes)); err != nil {
189+
t.Fatalf("unexpected halt: %v", err)
190+
}
191+
if applier.lastRotationIdx != wantIdx {
192+
t.Fatalf("ApplyRotation observed raftIdx=%d, want %d", applier.lastRotationIdx, wantIdx)
193+
}
194+
}
195+
128196
func TestApply_Rotation_HappyPath(t *testing.T) {
129197
t.Parallel()
130198
applier := &fakeApplier{}

0 commit comments

Comments
 (0)