github.com/yaling888/clash@v1.53.0/component/process/process_test.go (about) 1 package process 2 3 import ( 4 "net" 5 "net/netip" 6 "os" 7 "path/filepath" 8 "runtime" 9 "strings" 10 "testing" 11 12 "github.com/stretchr/testify/assert" 13 ) 14 15 func testConn(t *testing.T, network, address string) { 16 l, err := net.Listen(network, address) 17 if err != nil { 18 assert.FailNow(t, "Listen failed", err) 19 } 20 defer l.Close() 21 22 conn, err := net.Dial("tcp", l.Addr().String()) 23 if err != nil { 24 assert.FailNow(t, "Dial failed", err) 25 } 26 defer conn.Close() 27 28 rConn, err := l.Accept() 29 if err != nil { 30 assert.FailNow(t, "Accept conn failed", err) 31 } 32 defer rConn.Close() 33 34 path, err := FindProcessPath(TCP, conn.LocalAddr().(*net.TCPAddr).AddrPort(), conn.RemoteAddr().(*net.TCPAddr).AddrPort()) 35 if err != nil { 36 assert.FailNow(t, "Find process path failed", err) 37 } 38 39 exePath, err := getExePath(path) 40 if err != nil { 41 assert.FailNow(t, "Get executable failed", err) 42 } 43 44 assert.Equal(t, exePath, path) 45 } 46 47 func TestFindProcessPathTCP(t *testing.T) { 48 t.Run("v4", func(t *testing.T) { 49 testConn(t, "tcp4", "127.0.0.1:0") 50 }) 51 t.Run("v6", func(t *testing.T) { 52 testConn(t, "tcp6", "[::1]:0") 53 }) 54 } 55 56 func testPacketConn(t *testing.T, network, lAddress, rAddress string) { 57 lConn, err := net.ListenPacket(network, lAddress) 58 if err != nil { 59 assert.FailNow(t, "ListenPacket failed", err) 60 } 61 defer lConn.Close() 62 63 rConn, err := net.ListenPacket(network, rAddress) 64 if err != nil { 65 assert.FailNow(t, "ListenPacket failed", err) 66 } 67 defer rConn.Close() 68 69 _, err = lConn.WriteTo([]byte{0}, rConn.LocalAddr()) 70 if err != nil { 71 assert.FailNow(t, "Send message failed", err) 72 } 73 74 _, lAddr, err := rConn.ReadFrom([]byte{0}) 75 if err != nil { 76 assert.FailNow(t, "Receive message failed", err) 77 } 78 79 path, err := FindProcessPath(UDP, lAddr.(*net.UDPAddr).AddrPort(), rConn.LocalAddr().(*net.UDPAddr).AddrPort()) 80 if err != nil { 81 assert.FailNow(t, "Find process path", err) 82 } 83 84 exePath, err := getExePath(path) 85 if err != nil { 86 assert.FailNow(t, "Find executable", err) 87 } 88 89 assert.Equal(t, exePath, path) 90 } 91 92 func TestFindProcessPathUDP(t *testing.T) { 93 t.Run("v4", func(t *testing.T) { 94 testPacketConn(t, "udp4", "127.0.0.1:0", "127.0.0.1:0") 95 }) 96 t.Run("v6", func(t *testing.T) { 97 testPacketConn(t, "udp6", "[::1]:0", "[::1]:0") 98 }) 99 t.Run("v4AnyLocal", func(t *testing.T) { 100 testPacketConn(t, "udp4", "0.0.0.0:0", "127.0.0.1:0") 101 }) 102 t.Run("v6AnyLocal", func(t *testing.T) { 103 testPacketConn(t, "udp6", "[::]:0", "[::1]:0") 104 }) 105 } 106 107 func BenchmarkFindProcessName(b *testing.B) { 108 from := netip.MustParseAddrPort("127.0.0.1:11447") 109 to := netip.MustParseAddrPort("127.0.0.1:33669") 110 111 b.ResetTimer() 112 for i := 0; i < b.N; i++ { 113 FindProcessPath(TCP, from, to) 114 } 115 } 116 117 func getExePath(path string) (string, error) { 118 exePath, err := os.Executable() 119 if err != nil { 120 return "", err 121 } 122 123 if runtime.GOOS == "darwin" { 124 if strings.HasPrefix(path, "/private") && !strings.HasPrefix(exePath, "/private") { 125 exePath = filepath.Join("/private", exePath) 126 } 127 } 128 129 return exePath, nil 130 }