platform: modularize api/gui, add docs-tests-web foundation, and refresh root config
This commit is contained in:
199
selective-vpn-api/app/transport_netns_test.go
Normal file
199
selective-vpn-api/app/transport_netns_test.go
Normal file
@@ -0,0 +1,199 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user