Files
funknetz/station/protocol_select_test.go
T

153 lines
4.3 KiB
Go

package station_test
import (
"context"
"net"
"os"
"testing"
"time"
"gitea.neitzel.de/konrad/funknetz/station"
)
func TestVersionErrorFallsBackWhenTheMaximumIs2(t *testing.T) {
for _, msg := range []string{
"Unsupported protocol version 3.0. May be at most 2.0.",
"Unsupported protocol version 3.0. May be at most 2.5.",
} {
t.Run(msg, func(t *testing.T) {
refl := newReflector(t)
path := writeConfigFile(t, configJSON(t, "127.0.0.1", refl.port, "DL1ABC", "key", 20))
clock := newFakeClock()
st, err := station.New(station.Options{ConfigPath: path, Clock: clock})
if err != nil {
t.Fatal(err)
}
ctx, cancel := context.WithCancel(t.Context())
defer cancel()
go func() {
// Run's error is observed through State, which is the station seam.
_ = st.Run(ctx)
}()
refl.accept(t)
typ, body := refl.readFrame(t)
if typ != 5 || !versionIs(body, 3, 0) {
t.Fatalf("type %d body %v", typ, body)
}
refl.writeFrame(t, 13, appendStr(nil, msg))
refl.accept(t)
typ, body = refl.readFrame(t)
if typ != 5 || !versionIs(body, 2, 0) {
t.Fatalf("fallback type %d body %v", typ, body)
}
})
}
}
func TestVersionErrorBelow2Stops(t *testing.T) {
for _, msg := range []string{
"Unsupported protocol version 3.0. May be at most 1.9.",
"Unsupported protocol version 3.0. May be at most 0.6.",
} {
t.Run(msg, func(t *testing.T) {
refl := newReflector(t)
path := writeConfigFile(t, configJSON(t, "127.0.0.1", refl.port, "DL1ABC", "key", 20))
clock := newFakeClock()
st, err := station.New(station.Options{ConfigPath: path, Clock: clock})
if err != nil {
t.Fatal(err)
}
ctx, cancel := context.WithCancel(t.Context())
defer cancel()
go func() {
// Run's error is observed through State, which is the station seam.
_ = st.Run(ctx)
}()
refl.accept(t)
refl.readFrame(t)
refl.writeFrame(t, 13, appendStr(nil, msg))
got, err := st.Wait(ctx, func(s station.State) bool { return s.Detail == msg })
if err != nil {
t.Fatal(err)
}
if got.Connection != "Disconnected" || got.Protocol != "" {
t.Fatalf("State = %+v", got)
}
clock.Advance(2 * time.Second)
refl.ln.(*net.TCPListener).SetDeadline(time.Now().Add(150 * time.Millisecond))
if conn, err := refl.ln.Accept(); err == nil {
conn.Close()
t.Fatal("retried")
}
})
}
}
func TestDowngradeOtherThan2Stops(t *testing.T) {
for _, tc := range []struct {
major, minor uint16
want string
}{
{1, 0, "Unsupported protocol version 1.0"},
{4, 2, "Unsupported protocol version 4.2"},
} {
t.Run(tc.want, func(t *testing.T) {
refl := newReflector(t)
path := writeConfigFile(t, configJSON(t, "127.0.0.1", refl.port, "DL1ABC", "key", 20))
clock := newFakeClock()
st, err := station.New(station.Options{ConfigPath: path, Clock: clock})
if err != nil {
t.Fatal(err)
}
ctx, cancel := context.WithCancel(t.Context())
defer cancel()
go func() {
// Run's error is observed through State, which is the station seam.
_ = st.Run(ctx)
}()
refl.accept(t)
refl.readFrame(t)
refl.writeFrame(t, 6, versionWire(tc.major, tc.minor))
got, err := st.Wait(ctx, func(s station.State) bool { return s.Detail == tc.want })
if err != nil {
t.Fatal(err)
}
if got.Protocol != "" || got.Connection != "Disconnected" {
t.Fatalf("State = %+v", got)
}
clock.Advance(2 * time.Second)
refl.ln.(*net.TCPListener).SetDeadline(time.Now().Add(150 * time.Millisecond))
if conn, err := refl.ln.Accept(); err == nil {
conn.Close()
t.Fatal("retried")
}
})
}
}
func TestDowngradeDoesNotCreateTheCertificateDirectory(t *testing.T) {
refl := newReflector(t)
dir := t.TempDir()
path := dir + "/funknetz.json"
body := configWithDir(t, "127.0.0.1", refl.port, "DL1ABC", "key", 20, "./funknetz", "")
if err := os.WriteFile(path, []byte(body), 0o600); err != nil {
t.Fatal(err)
}
clock := newFakeClock()
st, err := station.New(station.Options{ConfigPath: path, Clock: clock})
if err != nil {
t.Fatal(err)
}
ctx, cancel := context.WithCancel(t.Context())
defer cancel()
go func() {
// Run's error is observed through State, which is the station seam.
_ = st.Run(ctx)
}()
refl.accept(t)
declineTo2(t, refl)
if _, err := os.Stat(dir + "/funknetz"); err == nil {
t.Fatal("created the certificate directory on a 2.0 fallback")
}
}