90 lines
3.4 KiB
Go
90 lines
3.4 KiB
Go
// Copyright (c) 2026 Storm Dragon
|
|
// Authors: Storm Dragon, Angus Kola
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
package remoteinput
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"errors"
|
|
"testing"
|
|
)
|
|
|
|
func TestHelperOperationCodec(t *testing.T) {
|
|
for _, operation := range []Operation{
|
|
{Kind: Down, Epoch: 7, Sequence: 1, Name: "Control_R"},
|
|
{Kind: Up, Epoch: 7, Sequence: 2, Name: "KP_Enter"},
|
|
{Kind: Heartbeat, Epoch: 7, Sequence: ^uint64(0)},
|
|
{Kind: Close, Epoch: ^uint64(0), Sequence: 1},
|
|
} {
|
|
frame, err := EncodeOperation(operation)
|
|
if err != nil || len(frame) != OperationSize || frame[0] != 1 || frame[1] != operation.Kind ||
|
|
binary.BigEndian.Uint64(frame[4:12]) != operation.Epoch || binary.BigEndian.Uint64(frame[12:20]) != operation.Sequence {
|
|
t.Fatal("wrong fixed operation representation", err)
|
|
}
|
|
if decoded, err := DecodeOperation(frame); err != nil || decoded != operation {
|
|
t.Fatal("operation identity changed", err)
|
|
}
|
|
}
|
|
for _, operation := range []Operation{
|
|
{Kind: 0, Epoch: 7, Sequence: 1}, {Kind: Heartbeat, Sequence: 1},
|
|
{Kind: Heartbeat, Epoch: 7}, {Kind: Down, Epoch: 7, Sequence: 1},
|
|
{Kind: Up, Epoch: 7, Sequence: 1, Name: "private unknown"},
|
|
{Kind: Down, Epoch: 7, Sequence: 1, Name: "a\x00"},
|
|
{Kind: Heartbeat, Epoch: 7, Sequence: 1, Name: "a"},
|
|
{Kind: Close, Epoch: 7, Sequence: 1, Name: "a"},
|
|
} {
|
|
if _, err := EncodeOperation(operation); !errors.Is(err, ErrProtocol) {
|
|
t.Fatal("invalid private operation was encoded")
|
|
}
|
|
}
|
|
frame, _ := EncodeOperation(Operation{Kind: Down, Epoch: 7, Sequence: 1, Name: "a"})
|
|
for _, index := range []int{0, 1, 2, 3, 21, OperationSize - 1} {
|
|
bad := append([]byte(nil), frame...)
|
|
bad[index] = 255
|
|
if value, err := DecodeOperation(bad); !errors.Is(err, ErrProtocol) || value != (Operation{}) {
|
|
t.Fatal("malformed version/kind/length/reserved/padding produced a partial operation")
|
|
}
|
|
}
|
|
for _, bad := range [][]byte{nil, frame[:OperationSize-1], append(frame, 0)} {
|
|
if _, err := DecodeOperation(bad); !errors.Is(err, ErrProtocol) {
|
|
t.Fatal("nonfixed frame was accepted")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestHelperAckCodec(t *testing.T) {
|
|
for _, ack := range []Ack{
|
|
{Kind: Ready, Epoch: 7}, {Kind: Accepted, Epoch: 7, Sequence: 1},
|
|
{Kind: Closed, Epoch: 7, Sequence: 2, Reason: ReasonClose},
|
|
{Kind: Closed, Epoch: 7, Sequence: ^uint64(0), Reason: ReasonEOF, CleanupFailed: true},
|
|
} {
|
|
frame, err := EncodeAck(ack)
|
|
if err != nil || len(frame) != AckSize {
|
|
t.Fatal("acknowledgement was not fixed size", err)
|
|
}
|
|
if decoded, err := DecodeAck(frame); err != nil || decoded != ack {
|
|
t.Fatal("acknowledgement lost cleanup/sequence identity", err)
|
|
}
|
|
}
|
|
for _, ack := range []Ack{
|
|
{Kind: Ready}, {Kind: Ready, Epoch: 7, Sequence: 1},
|
|
{Kind: Ready, Epoch: 7, CleanupFailed: true}, {Kind: Accepted, Epoch: 7},
|
|
{Kind: Accepted, Epoch: 7, Sequence: 1, Reason: ReasonClose},
|
|
{Kind: Closed, Epoch: 7}, {Kind: Closed, Epoch: 7, Reason: 255},
|
|
{Kind: 255, Epoch: 7},
|
|
} {
|
|
if _, err := EncodeAck(ack); !errors.Is(err, ErrProtocol) {
|
|
t.Fatal("invalid acknowledgement was encoded")
|
|
}
|
|
}
|
|
frame, _ := EncodeAck(Ack{Kind: Closed, Epoch: 7, Reason: ReasonEOF})
|
|
for _, index := range []int{0, 1, 2, 3} {
|
|
bad := append([]byte(nil), frame...)
|
|
bad[index] = 255
|
|
if value, err := DecodeAck(bad); !errors.Is(err, ErrProtocol) || value != (Ack{}) {
|
|
t.Fatal("invalid acknowledgement flags or version were accepted")
|
|
}
|
|
}
|
|
}
|