Files
elmprodvpn/selective-vpn-api/app/transport_bootstrap_bypass_test.go

119 lines
3.3 KiB
Go

package app
import (
"os"
"path/filepath"
"strings"
"testing"
"time"
)
func TestTransportNormalizeBootstrapTarget(t *testing.T) {
cases := map[string]string{
"vless://user@example.com:443?type=tcp": "example.com",
"example.com:8443": "example.com",
"203.0.113.10:443": "203.0.113.10",
"[2001:db8::1]:443": "2001:db8::1",
"https://api.example.net/path?q=1": "api.example.net",
}
for in, want := range cases {
got := transportNormalizeBootstrapTarget(in)
if got != want {
t.Fatalf("normalize mismatch for %q: got=%q want=%q", in, got, want)
}
}
}
func TestTransportCollectSingBoxConfigCandidates(t *testing.T) {
tmp := t.TempDir()
cfg := filepath.Join(tmp, "singbox.json")
body := `{
"log": {"level":"info"},
"outbounds": [
{"type":"vless","server":"n3.elmprod.tech","server_port":40903},
{"type":"shadowsocks","server":"198.51.100.5","server_port":443}
]
}`
if err := os.WriteFile(cfg, []byte(body), 0o644); err != nil {
t.Fatalf("write config: %v", err)
}
client := TransportClient{
ID: "sg-test",
Kind: TransportClientSingBox,
Config: map[string]any{
"config_path": cfg,
},
}
got := transportCollectSingBoxConfigCandidates(client)
joined := strings.Join(got, ",")
if !strings.Contains(joined, "n3.elmprod.tech") {
t.Fatalf("missing server host in candidates: %#v", got)
}
if !strings.Contains(joined, "198.51.100.5") {
t.Fatalf("missing server ip in candidates: %#v", got)
}
}
func TestTransportSystemdActionAppliesSingBoxBootstrapBypass(t *testing.T) {
origRunner := transportRunCommand
origPath := transportBootstrapStatePath
defer func() {
transportRunCommand = origRunner
transportBootstrapStatePath = origPath
}()
tmp := t.TempDir()
transportBootstrapStatePath = filepath.Join(tmp, "bootstrap-routes.json")
calls := make([]string, 0, 8)
transportRunCommand = func(_ time.Duration, name string, args ...string) (string, string, int, error) {
cmd := name + " " + strings.Join(args, " ")
calls = append(calls, cmd)
switch cmd {
case "ip -4 route show table main default":
return "default via 192.0.2.1 dev eth0\n", "", 0, nil
case "ip -4 route replace 203.0.113.10/32 table agvpn via 192.0.2.1 dev eth0":
return "", "", 0, nil
case "systemctl start singbox@sg-test.service":
return "", "", 0, nil
default:
return "", "", 0, nil
}
}
client := TransportClient{
ID: "sg-test",
Kind: TransportClientSingBox,
Config: map[string]any{
"runner": "systemd",
"unit": "singbox@.service",
"bootstrap_host": "203.0.113.10",
},
}
res := transportSystemdBackend{}.Action(client, "start")
if !res.OK {
t.Fatalf("expected action success, got %#v", res)
}
gotCalls := strings.Join(calls, " | ")
want := []string{
"ip -4 route show table main default",
"ip -4 route replace 203.0.113.10/32 table agvpn via 192.0.2.1 dev eth0",
"systemctl start singbox@sg-test.service",
}
for _, part := range want {
if !strings.Contains(gotCalls, part) {
t.Fatalf("expected call %q, got %s", part, gotCalls)
}
}
data, err := os.ReadFile(transportBootstrapStatePath)
if err != nil {
t.Fatalf("read bootstrap state: %v", err)
}
text := string(data)
if !strings.Contains(text, "203.0.113.10") || !strings.Contains(text, "sg-test") {
t.Fatalf("unexpected bootstrap state: %s", text)
}
}