Files
2026-07-11 08:42:52 +08:00

86 lines
2.1 KiB
Go

//go:build linux
package netns
import (
"bufio"
"os"
"strconv"
"strings"
"testing"
"time"
"github.com/sagernet/sing-box/adapter"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/option"
F "github.com/sagernet/sing/common/format"
"github.com/sagernet/sing/common/logger"
)
func TestUnshareNamespace(t *testing.T) {
if os.Getenv("NETNS_TEST_HOLDER") == "1" {
Hold()
}
pipeReader, pipeWriter, err := os.Pipe()
if err != nil {
t.Fatal(err)
}
defer pipeReader.Close()
defer pipeWriter.Close()
os.Setenv("NETNS_TEST_HOLDER", "1")
defer os.Unsetenv("NETNS_TEST_HOLDER")
manager, err := NewManager(logger.NOP(), []option.NetworkNamespace{{
Type: C.NetNsTypeUnshare,
Tag: "test",
UnshareOptions: option.UnshareNetworkNamespaceOptions{
PidFile: "/proc/self/fd/" + F.ToString(pipeWriter.Fd()),
},
}}, []string{"/proc/self/exe", "-test.run=^TestUnshareNamespace$"})
if err != nil {
t.Fatal(err)
}
err = manager.Start(adapter.StartStateInitialize)
if err != nil {
t.Fatal(err)
}
defer manager.Close()
pipeReader.SetReadDeadline(time.Now().Add(10 * time.Second))
pidLine, err := bufio.NewReader(pipeReader).ReadString('\n')
if err != nil {
t.Fatal("read pid from pipe: ", err)
}
pid, err := strconv.Atoi(strings.TrimSuffix(pidLine, "\n"))
if err != nil {
t.Fatal("parse pid: ", err)
}
resolvedPath := manager.ResolvePath("test")
if resolvedPath != netnsPath(pid) {
t.Fatal("resolved path ", resolvedPath, " does not match pid ", pid)
}
currentNs, err := os.Readlink("/proc/thread-self/ns/net")
if err != nil {
t.Fatal(err)
}
holderNs, err := os.Readlink(resolvedPath)
if err != nil {
t.Fatal("holder netns not accessible: ", err)
}
if currentNs == holderNs {
t.Fatal("holder is in the current netns")
}
err = manager.Close()
if err != nil {
t.Fatal(err)
}
for deadline := time.Now().Add(10 * time.Second); time.Now().Before(deadline); time.Sleep(10 * time.Millisecond) {
_, err = os.Stat("/proc/" + strconv.Itoa(pid))
if err != nil {
return
}
}
t.Fatal("holder process did not exit after close")
}