quorate/packages/mesh-init/abi_test.go

97 lines
3.1 KiB
Go
Raw Normal View History

package main
import (
"bytes"
"encoding/binary"
"math"
"testing"
)
func TestLayout(t *testing.T) {
for _, test := range []struct {
value any
size int
}{
{tableInfo{}, 84}, {replaceHead{}, 96}, {ipMatch{}, 84}, {ruleHeader{}, 112}, {counter{}, 16},
} {
if size := binary.Size(test.value); size != test.size {
t.Errorf("%T size = %d, want %d", test.value, size, test.size)
}
}
}
func TestTable(t *testing.T) {
value := config{1234, 5678, 9012, []uint16{80, 443}}
data := table(value, 5, 0x12345678)
var head replaceHead
if err := binary.Read(bytes.NewReader(data), binary.NativeEndian, &head); err != nil {
t.Fatal(err)
}
if string(bytes.TrimRight(head.Name[:], "\x00")) != "nat" || head.Valid != 27 || head.Count != 11 || int(head.Size) != len(data)-96 || head.OldCount != 5 || head.Address != 0x12345678 {
t.Fatalf("invalid replacement header: %+v", head)
}
body := data[96:]
starts := map[uint32]bool{}
var entries [][]byte
for offset := 0; offset < len(body); {
var rule ruleHeader
if err := binary.Read(bytes.NewReader(body[offset:]), binary.NativeEndian, &rule); err != nil {
t.Fatal(err)
}
if rule.Next%8 != 0 || rule.Target < 112 || rule.Next < rule.Target+32 {
t.Fatalf("invalid rule offsets: %+v", rule)
}
starts[size32(offset)] = true
entries = append(entries, body[offset:offset+int(rule.Next)])
offset += int(rule.Next)
}
if len(entries) != 11 {
t.Fatalf("entry count = %d", len(entries))
}
for _, hook := range []int{0, 1, 3, 4} {
if !starts[head.Hooks[hook]] || !starts[head.Underflow[hook]] {
t.Errorf("hook %d does not point to entry boundaries", hook)
}
policy := body[head.Underflow[hook]:]
if verdict := binary.NativeEndian.Uint32(policy[144:]); verdict != math.MaxUint32-1 {
t.Errorf("hook %d has non-ACCEPT policy", hook)
}
}
for index, port := range map[int]uint16{0: 80, 1: 443} {
if got := binary.NativeEndian.Uint16(entries[index][148:]); got != port {
t.Errorf("inbound exclusion = %d, want %d", got, port)
}
}
if binary.BigEndian.Uint16(entries[2][160:]) != value.inbound || binary.BigEndian.Uint16(entries[7][160:]) != value.outbound {
t.Error("redirect ports differ from configuration")
}
if binary.NativeEndian.Uint32(entries[5][144:]) != value.proxyUID || !bytes.Equal(entries[6][32:35], []byte{'l', 'o', 0}) || !bytes.Equal(entries[6][64:67], []byte{255, 255, 255}) {
t.Error("proxy UID or loopback exemption differs")
}
if !bytes.Contains(entries[10], []byte("ERROR")) {
t.Error("missing table terminator")
}
without := table(config{inbound: 1, outbound: 2}, 3, 0)
if got := binary.NativeEndian.Uint32(without[36:]); got != 9 {
t.Errorf("empty exclusions produce %d entries", got)
}
}
func TestSizeBounds(t *testing.T) {
if size16(math.MaxUint16) != math.MaxUint16 || size32(math.MaxUint32) != math.MaxUint32 {
t.Fatal("maximum ABI sizes differ")
}
for _, check := range []func(){
func() { extension("tcp", 0, make([]byte, 65535)) },
func() { size16(-1) }, func() { size32(-1) }, func() { size32(math.MaxUint32 + 1) },
} {
func() {
defer func() {
if recover() == nil {
t.Error("unrepresentable ABI size accepted")
}
}()
check()
}()
}
}