feat(netdetect): detect WAN interface, gateways and addresses
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user