package app import ( "os" "path/filepath" "strings" "testing" "time" ) func TestTransportWrapExecWithNetns(t *testing.T) { client := TransportClient{ ID: "sg-1", Config: map[string]any{ "netns_enabled": true, "netns_name": "svpn-test", "netns_exec_mode": "ip", }, } cmd := transportWrapExecWithNetns(client, "/usr/bin/sing-box run -c /etc/singbox/test.json") if !strings.Contains(cmd, "'ip' 'netns' 'exec' 'svpn-test'") { t.Fatalf("expected wrapped command with netns exec, got: %s", cmd) } if !strings.Contains(cmd, "'/bin/sh' '-lc'") { t.Fatalf("expected wrapped command to keep payload shell execution, got: %s", cmd) } } func TestTransportWrapExecWithNetnsNsenter(t *testing.T) { client := TransportClient{ ID: "sg-1", Config: map[string]any{ "netns_enabled": true, "netns_name": "svpn-test", "netns_exec_mode": "nsenter", "netns_nsenter_bin": "/usr/bin/nsenter", }, } cmd := transportWrapExecWithNetns(client, "/usr/bin/sing-box run -c /etc/singbox/test.json") if !strings.Contains(cmd, "'/usr/bin/nsenter' '--net=/var/run/netns/svpn-test' '--'") { t.Fatalf("expected wrapped command with nsenter, got: %s", cmd) } if !strings.Contains(cmd, "'/bin/sh' '-lc'") { t.Fatalf("expected wrapped command to keep payload shell execution, got: %s", cmd) } } func TestTransportNetnsExecCommandModes(t *testing.T) { clientNS := TransportClient{ ID: "sg-1", Config: map[string]any{ "netns_exec_mode": "nsenter", "netns_nsenter_bin": "/usr/bin/nsenter", }, } name, args, err := transportNetnsExecCommand(clientNS, "svpn-test", "ip", "link", "show") if err != nil { t.Fatalf("nsenter mode command error: %v", err) } if name != "/usr/bin/nsenter" { t.Fatalf("expected nsenter binary, got: %q", name) } if len(args) < 5 || args[0] != "--net=/var/run/netns/svpn-test" || args[1] != "--" || args[2] != "ip" { t.Fatalf("unexpected nsenter args: %#v", args) } clientIP := TransportClient{ ID: "sg-1", Config: map[string]any{ "netns_exec_mode": "ip", "netns_ip_bin": "/sbin/ip", }, } name, args, err = transportNetnsExecCommand(clientIP, "svpn-test", "ip", "link", "show") if err != nil { t.Fatalf("ip mode command error: %v", err) } if name != "/sbin/ip" { t.Fatalf("expected ip binary, got: %q", name) } if len(args) < 6 || args[0] != "netns" || args[1] != "exec" || args[2] != "svpn-test" || args[3] != "ip" { t.Fatalf("unexpected ip args: %#v", args) } } func TestTransportSystemdBackendProvisionWrapsNetnsExec(t *testing.T) { origRunner := transportRunCommand origUnitsDir := transportSystemdUnitsDir defer func() { transportRunCommand = origRunner transportSystemdUnitsDir = origUnitsDir }() tmpDir := t.TempDir() transportSystemdUnitsDir = tmpDir transportRunCommand = func(_ time.Duration, name string, args ...string) (string, string, int, error) { cmd := name + " " + strings.Join(args, " ") if cmd == "systemctl daemon-reload" { return "", "", 0, nil } return "", "", 0, nil } client := TransportClient{ ID: "sg-netns", Kind: TransportClientSingBox, Config: map[string]any{ "runner": "systemd", "unit": "sg-netns.service", "exec_start": "/usr/bin/sing-box run -c /etc/singbox/eu.json", "netns_enabled": true, "netns_name": "svpn-test", }, } res := selectTransportBackend(client).Provision(client) if !res.OK { t.Fatalf("expected provision success, got %#v", res) } data, err := os.ReadFile(filepath.Join(tmpDir, "sg-netns.service")) if err != nil { t.Fatalf("failed to read unit: %v", err) } text := string(data) if !strings.Contains(text, "netns") || !strings.Contains(text, "svpn-test") { t.Fatalf("expected netns exec in unit ExecStart, got: %s", text) } } func TestTransportSystemdBackendActionNetnsStrictFailure(t *testing.T) { origRunner := transportRunCommand defer func() { transportRunCommand = origRunner }() transportRunCommand = func(_ time.Duration, name string, args ...string) (string, string, int, error) { cmd := name + " " + strings.Join(args, " ") if cmd == "ip netns list" { return "", "cannot list netns", 1, nil } return "", "", 0, nil } client := TransportClient{ ID: "sg-netns", Kind: TransportClientSingBox, Config: map[string]any{ "runner": "systemd", "unit": "singbox-test.service", "netns_enabled": true, "netns_setup_strict": true, }, } res := selectTransportBackend(client).Action(client, "start") if res.OK { t.Fatalf("expected strict netns setup failure, got %#v", res) } if res.Code != "TRANSPORT_BACKEND_NETNS_SETUP_FAILED" { t.Fatalf("unexpected error code: %#v", res) } } func TestTransportSystemdBackendActionNetnsWarningNonStrict(t *testing.T) { origRunner := transportRunCommand defer func() { transportRunCommand = origRunner }() calls := make([]string, 0, 4) transportRunCommand = func(_ time.Duration, name string, args ...string) (string, string, int, error) { cmd := name + " " + strings.Join(args, " ") calls = append(calls, cmd) if cmd == "ip netns list" { return "", "cannot list netns", 1, nil } if cmd == "systemctl start singbox-test.service" { return "", "", 0, nil } return "", "", 0, nil } client := TransportClient{ ID: "sg-netns", Kind: TransportClientSingBox, Config: map[string]any{ "runner": "systemd", "unit": "singbox-test.service", "netns_enabled": true, }, } res := selectTransportBackend(client).Action(client, "start") if !res.OK { t.Fatalf("expected non-strict start success with warning, got %#v", res) } if !strings.Contains(strings.ToLower(res.Message), "warnings") { t.Fatalf("expected warning marker in message, got %#v", res) } if !strings.Contains(strings.ToLower(res.Stderr), "netns:") { t.Fatalf("expected netns warning in stderr, got %#v", res) } if !strings.Contains(strings.Join(calls, " | "), "systemctl start singbox-test.service") { t.Fatalf("expected systemctl start call, got %#v", calls) } }