Files
prx/internal/netdetect/netdetect_test.go
T

128 lines
4.1 KiB
Go
Raw Normal View History

// SPDX-License-Identifier: MIT
package netdetect
import (
"context"
"strings"
"testing"
"prx/internal/execx"
)
func fake(handler func(name string, args []string) (string, error)) *execx.Fake {
return &execx.Fake{Handler: func(name string, args []string, _ []byte) (execx.Result, error) {
out, err := handler(name, args)
if err != nil {
return execx.Result{}, err
}
return execx.Result{Stdout: []byte(out)}, nil
}}
}
func TestDetect(t *testing.T) {
r := fake(func(name string, args []string) (string, error) {
joined := strings.Join(args, " ")
switch {
case joined == "-j route show default":
return `[{"dst":"default","gateway":"192.168.1.1","dev":"wlan0","metric":600}]`, nil
case joined == "-6 -j route show default":
return `[]`, nil
case joined == "-j addr show dev wlan0":
return `[{"ifname":"wlan0","addr_info":[
{"family":"inet","local":"192.168.1.100","prefixlen":24,"scope":"global"},
{"family":"inet6","local":"fe80::abcd","prefixlen":64,"scope":"link"}]}]`, nil
}
return "", nil
})
wan, err := Detect(context.Background(), r, "", "", "")
if err != nil {
t.Fatalf("Detect: %v", err)
}
if wan.Interface != "wlan0" {
t.Errorf("interface = %q", wan.Interface)
}
if wan.Gateway4 != "192.168.1.1" {
t.Errorf("gateway4 = %q", wan.Gateway4)
}
if wan.Gateway6 != "" {
t.Errorf("gateway6 = %q, want empty", wan.Gateway6)
}
if len(wan.Local4) != 1 || wan.Local4[0] != "192.168.1.100" {
t.Errorf("local4 = %v", wan.Local4)
}
if len(wan.Local6) != 0 {
t.Errorf("local6 = %v, want none (link-local excluded)", wan.Local6)
}
}
func TestDetectPrefersLowestMetric(t *testing.T) {
r := fake(func(_ string, args []string) (string, error) {
joined := strings.Join(args, " ")
if joined == "-j route show default" {
return `[{"dst":"default","gateway":"10.0.0.1","dev":"eth9","metric":900},
{"dst":"default","gateway":"192.168.1.1","dev":"wlan0","metric":100}]`, nil
}
if strings.Contains(joined, "addr show dev wlan0") {
return `[{"ifname":"wlan0","addr_info":[{"family":"inet","local":"192.168.1.100","prefixlen":24,"scope":"global"}]}]`, nil
}
return `[]`, nil
})
wan, err := Detect(context.Background(), r, "", "", "")
if err != nil {
t.Fatalf("Detect: %v", err)
}
if wan.Interface != "wlan0" || wan.Gateway4 != "192.168.1.1" {
t.Fatalf("picked %s/%s, want wlan0/192.168.1.1", wan.Interface, wan.Gateway4)
}
}
func TestDetectOverride(t *testing.T) {
r := fake(func(_ string, args []string) (string, error) {
if strings.Join(args, " ") == "-j route show default" {
return `[{"dst":"default","gateway":"192.168.1.1","dev":"wlan0","metric":100}]`, nil
}
if strings.Contains(strings.Join(args, " "), "addr show dev wlan0") {
return `[{"ifname":"wlan0","addr_info":[{"family":"inet","local":"192.168.1.100","prefixlen":24,"scope":"global"}]}]`, nil
}
return `[]`, nil
})
wan, err := Detect(context.Background(), r, "wlan0", "10.9.9.9", "")
if err != nil {
t.Fatalf("Detect: %v", err)
}
if wan.Gateway4 != "10.9.9.9" {
t.Fatalf("gateway override not applied: %q", wan.Gateway4)
}
}
func TestDetectNoDefaultRoute(t *testing.T) {
r := fake(func(_ string, _ []string) (string, error) { return `[]`, nil })
if _, err := Detect(context.Background(), r, "", "", ""); err == nil {
t.Fatal("expected error when no default route exists")
}
}
func TestDetectIPv6OnlyUplink(t *testing.T) {
r := fake(func(_ string, args []string) (string, error) {
joined := strings.Join(args, " ")
switch {
case joined == "-j route show default":
return `[]`, nil
case joined == "-6 -j route show default":
return `[{"dst":"default","gateway":"2001:db8::1","dev":"eth0","metric":100}]`, nil
case joined == "-j addr show dev eth0":
return `[{"ifname":"eth0","addr_info":[{"family":"inet6","local":"2001:db8::5","prefixlen":64,"scope":"global"}]}]`, nil
}
return `[]`, nil
})
wan, err := Detect(context.Background(), r, "", "", "")
if err != nil {
t.Fatalf("Detect: %v", err)
}
if wan.Interface != "eth0" || wan.Gateway4 != "" || wan.Gateway6 != "2001:db8::1" {
t.Fatalf("ipv6-only detection = %+v", wan)
}
}