128 lines
4.1 KiB
Go
128 lines
4.1 KiB
Go
// 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)
|
||
|
|
}
|
||
|
|
}
|