Files

96 lines
3.6 KiB
Go

package domain
import (
"bytes"
"errors"
"strings"
"testing"
)
func TestAuthenticatedCursorRoundTrip_HP_CTL_06(t *testing.T) {
t.Parallel()
codec, err := NewCursorCodec(bytes.Repeat([]byte{0x42}, 32))
if err != nil {
t.Fatal(err)
}
filters := HashCursorFilters([]byte("client=host-1\x00streams=stdout"))
want := Cursor{Kind: CursorKindOutput, FilterHash: filters, Position: []byte("uuid/event/offset"), SnapshotBoundary: []byte("upper-event")}
token, err := codec.Encode(want)
if err != nil {
t.Fatal(err)
}
got, err := codec.Decode(token, CursorKindOutput, filters)
if err != nil {
t.Fatal(err)
}
if got.Kind != want.Kind || got.FilterHash != want.FilterHash || !bytes.Equal(got.Position, want.Position) || !bytes.Equal(got.SnapshotBoundary, want.SnapshotBoundary) {
t.Fatalf("decoded cursor = %+v, want %+v", got, want)
}
}
func TestCursorForgeryAndFilterBinding_BH_CTL_01(t *testing.T) {
t.Parallel()
codec, _ := NewCursorCodec(bytes.Repeat([]byte{0x42}, 32))
filters := HashCursorFilters([]byte("client=one"))
token, _ := codec.Encode(Cursor{Kind: CursorKindCommands, FilterHash: filters, Position: []byte("position"), SnapshotBoundary: []byte("boundary")})
forged := []byte(token)
forged[len(forged)/2] ^= 1
if _, err := codec.Decode(string(forged), CursorKindCommands, filters); !errors.Is(err, ErrInvalidCursor) {
t.Fatalf("forged cursor error = %v", err)
}
otherFilters := HashCursorFilters([]byte("client=two"))
if _, err := codec.Decode(token, CursorKindCommands, otherFilters); !errors.Is(err, ErrCursorFilterMismatch) {
t.Fatalf("filter mismatch error = %v", err)
}
if _, err := codec.Decode(token, CursorKindOutput, filters); !errors.Is(err, ErrInvalidCursor) {
t.Fatalf("kind mismatch error = %v", err)
}
for _, malformed := range []string{"", "***", strings.Repeat("a", 4096)} {
if _, err := codec.Decode(malformed, CursorKindCommands, filters); !errors.Is(err, ErrInvalidCursor) {
t.Errorf("malformed cursor %q error = %v", malformed[:min(len(malformed), 16)], err)
}
}
}
func TestCursorInputBounds_BH_CTL_01(t *testing.T) {
t.Parallel()
if _, err := NewCursorCodec([]byte("short")); !errors.Is(err, ErrInvalidCursor) {
t.Fatalf("short key error = %v", err)
}
codec, _ := NewCursorCodec(bytes.Repeat([]byte{1}, 32))
filter := HashCursorFilters(nil)
for _, cursor := range []Cursor{
{Kind: 0, FilterHash: filter, Position: []byte("x"), SnapshotBoundary: []byte("y")},
{Kind: CursorKindCommands, FilterHash: filter, SnapshotBoundary: []byte("y")},
{Kind: CursorKindCommands, FilterHash: filter, Position: bytes.Repeat([]byte("x"), maxCursorFieldBytes+1), SnapshotBoundary: []byte("y")},
} {
if _, err := codec.Encode(cursor); !errors.Is(err, ErrInvalidCursor) {
t.Errorf("invalid cursor error = %v", err)
}
}
}
// 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)
})
}