CI / test (push) Successful in 2m32s
Routes Java Edition connections by the hostname in the handshake, with wildcard domains, backend failover, PROXY protocol v2, cached server-list status from health probes, hot-reloaded config, and an admin page and metrics endpoint. Includes CI, tagged releases and a container image. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
88 lines
2.2 KiB
Go
88 lines
2.2 KiB
Go
package protocol
|
|
|
|
import (
|
|
"bytes"
|
|
"net"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestHandshakeRoundTrip(t *testing.T) {
|
|
in := BuildHandshake(767, "mc.example.com", 25565, 2)
|
|
h, raw, err := ReadHandshake(bytes.NewReader(in))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
want := Handshake{Protocol: 767, Host: "mc.example.com", Port: 25565, NextState: 2}
|
|
if h != want {
|
|
t.Fatalf("got %+v want %+v", h, want)
|
|
}
|
|
if !bytes.Equal(raw, in) {
|
|
t.Fatal("raw bytes not preserved")
|
|
}
|
|
}
|
|
|
|
func TestReadHandshakeRejects(t *testing.T) {
|
|
cases := map[string][]byte{
|
|
"legacy": {0xfe, 0x01, 0xfa},
|
|
"huge length": {0xff, 0xff, 0xff, 0xff, 0x07},
|
|
"zero length": {0x00},
|
|
"wrong id": Frame([]byte{0x05, 0x00}),
|
|
"short host": Frame([]byte{0x00, 0x01, 0x40, 'a'}),
|
|
"truncated": {0x10, 0x00},
|
|
}
|
|
for name, b := range cases {
|
|
if _, _, err := ReadHandshake(bytes.NewReader(b)); err == nil {
|
|
t.Errorf("%s: expected error", name)
|
|
}
|
|
}
|
|
if _, _, err := ReadHandshake(bytes.NewReader([]byte{0xfe, 0x01})); err != ErrLegacy {
|
|
t.Errorf("want ErrLegacy, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestVarInt(t *testing.T) {
|
|
if got := AppendVarInt(nil, 300); !bytes.Equal(got, []byte{0xac, 0x02}) {
|
|
t.Fatalf("got %x", got)
|
|
}
|
|
if got := AppendVarInt(nil, -1); len(got) != 5 {
|
|
t.Fatalf("negative should take 5 bytes, got %x", got)
|
|
}
|
|
}
|
|
|
|
func TestStatusExchange(t *testing.T) {
|
|
c, s := net.Pipe()
|
|
defer c.Close()
|
|
go func() {
|
|
defer s.Close()
|
|
ServeStatus(s, `{"ok":true}`)
|
|
}()
|
|
c.SetDeadline(time.Now().Add(2 * time.Second))
|
|
c.Write(Frame([]byte{0}))
|
|
id, payload, err := ReadPacket(c, maxStatus)
|
|
if err != nil || id != 0 || !bytes.Contains(payload, []byte(`{"ok":true}`)) {
|
|
t.Fatalf("id=%d payload=%q err=%v", id, payload, err)
|
|
}
|
|
c.Write(Frame(append([]byte{1}, 0, 0, 0, 0, 0, 0, 0, 42)))
|
|
id, payload, err = ReadPacket(c, 32)
|
|
if err != nil || id != 1 || payload[7] != 42 {
|
|
t.Fatalf("pong id=%d payload=%x err=%v", id, payload, err)
|
|
}
|
|
}
|
|
|
|
func TestQueryStatus(t *testing.T) {
|
|
c, s := net.Pipe()
|
|
defer c.Close()
|
|
go func() {
|
|
defer s.Close()
|
|
if _, _, err := ReadHandshake(s); err != nil {
|
|
return
|
|
}
|
|
ServeStatus(s, `{"players":{"online":3}}`)
|
|
}()
|
|
got, err := QueryStatus(c, "x", 25565, 2*time.Second)
|
|
if err != nil || got != `{"players":{"online":3}}` {
|
|
t.Fatalf("got %q err=%v", got, err)
|
|
}
|
|
}
|