test: cover cursor decoding and script integrity metrics

This commit is contained in:
2026-09-11 09:39:33 +00:00
parent 0e18af02bb
commit c5e9bc8b35
6 changed files with 39 additions and 5 deletions
+4 -2
View File
@@ -1157,8 +1157,10 @@ Use one declared test matrix and the same harness entry points everywhere:
native Windows integration suites, plus `smoke`, `idempotency`, `reconnect`,
and `retention` E2E scenarios;
- release candidates run every E2E scenario, including the resettable
interactive Windows VM matrix, Server Core smoke, destructive fault cases,
upgrade/recovery, and soak.
interactive Windows 10 VM matrix, destructive fault cases, upgrade/recovery,
and soak. Server Core, older-build, and ambiguous-multi-session smoke lanes
run when their dedicated fixtures are provisioned; they are explicitly
deferred compatibility work and do not block the Windows 10 v1 baseline.
CI allocates a run ID per job, always invokes `collect` after failure, and invokes
`reset` in an unconditional finalizer. Upload only the bounded redacted report,
+5 -3
View File
@@ -286,6 +286,8 @@ execution context. The normal `rvboxtest` console session remains the subject
of active-user and elevation tests. See [testing-vm.md](testing-vm.md) for the
exact fixture contract.
The VM is the minimum smoke lane, so native multi-session/ambiguous-session,
Server Core, and older-build entries remain explicitly blocked until their own
fixtures exist. Their pure selector tests remain mandatory.
The VM is the current Windows 10 v1 smoke lane. Native
multi-session/ambiguous-session, Server Core, and older-build entries are
explicitly deferred compatibility work until their own fixtures exist; they do
not block the Windows 10 v1 baseline. Their pure selector tests remain
mandatory.
+21
View File
@@ -72,3 +72,24 @@ func TestCursorInputBounds_BH_CTL_01(t *testing.T) {
}
}
}
// FuzzDecodeCursorBounded_SEC_CTL_02 exercises the token boundary shared by
// every cursor-resumable control read. Decode must reject malformed or forged
// input without panicking or allocating past its documented token ceiling.
func FuzzDecodeCursorBounded_SEC_CTL_02(f *testing.F) {
codec, err := NewCursorCodec(bytes.Repeat([]byte{0x42}, 32))
if err != nil {
f.Fatal(err)
}
filters := HashCursorFilters([]byte("client=host-1\x00streams=stdout"))
valid, err := codec.Encode(Cursor{Kind: CursorKindOutput, FilterHash: filters, Position: []byte("event/offset"), SnapshotBoundary: []byte("upper-event")})
if err != nil {
f.Fatal(err)
}
for _, seed := range []string{"", "***", valid, strings.Repeat("a", 4096)} {
f.Add(seed)
}
f.Fuzz(func(t *testing.T, token string) {
_, _ = codec.Decode(token, CursorKindOutput, filters)
})
}
+1
View File
@@ -256,6 +256,7 @@ func (service *Service) RunCommand(ctx context.Context, request *rvboxv1.RunComm
descriptor := spec.GetScript()
digest := sha256.Sum256(request.GetScriptContent())
if descriptor == nil || uint64(len(request.GetScriptContent())) != descriptor.GetSizeBytes() || !bytes.Equal(digest[:], descriptor.GetSha256()) {
service.incMetric("script_verification_failure")
return nil, controlError(codes.InvalidArgument, rvboxv1.ControlError_INVALID_ARGUMENT, "script_content does not match the script descriptor")
}
}
+7
View File
@@ -11,6 +11,7 @@ import (
rvboxv1 "github.com/rvbox/rvbox/gen/go/rvbox/v1"
"github.com/rvbox/rvbox/internal/agentproto"
"github.com/rvbox/rvbox/internal/domain"
"github.com/rvbox/rvbox/internal/observability"
"github.com/rvbox/rvbox/internal/server/store"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
@@ -70,6 +71,8 @@ func TestControlListAndGetViews_HP_CONTROL_01(t *testing.T) {
func TestRunCommandRequestIDIdempotencyAndValidation_BH_CONTROL_02(t *testing.T) {
service, persistence := newTestService(t)
defer persistence.Close()
metrics := observability.New()
service.metrics = metrics
ctx := context.Background()
registerControlClient(t, persistence, "win-a", rvboxv1.Platform_PLATFORM_WINDOWS, rvboxv1.ShellType_SHELL_POWERSHELL, 3)
issue := fixedIssue(0xa2)
@@ -102,6 +105,10 @@ func TestRunCommandRequestIDIdempotencyAndValidation_BH_CONTROL_02(t *testing.T)
if _, err := service.RunCommand(ctx, badScript); status.Code(err) != codes.InvalidArgument {
t.Fatalf("mismatched script code = %v", status.Code(err))
}
_, _, counters := metrics.Snapshot()
if counters["script_verification_failure"] != 1 {
t.Fatalf("script verification metrics = %#v", counters)
}
badTTL := proto.Clone(request).(*rvboxv1.RunCommandRequest)
badTTL.RequestId = fixedIssue(0xa4).String()
badTTL.QueueTtl = durationpb.New(-time.Second)
+1
View File
@@ -182,6 +182,7 @@ tests = [
"internal/agentproto/validate_test.go:FuzzDecodeOutputChunkBounded_SEC_PROTO_02",
"internal/server/control/jsonrpc_test.go:FuzzDecodeJSONRPCRequestBounded_SEC_CTL_01",
"internal/server/store/segment_test.go:FuzzDecodeSegmentRecordDoesNotEscapeBounds",
"internal/domain/cursor_test.go:FuzzDecodeCursorBounded_SEC_CTL_02",
]
[[requirements]]