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  }