From edd71de1c388671e0ccd96d3a514a2d5fff833b4 Mon Sep 17 00:00:00 2001 From: Darien Raymond Date: Mon, 7 Jan 2019 23:27:59 +0100 Subject: [PATCH] remove dependency on assert lib --- app/proxyman/outbound/handler_test.go | 7 +- common/net/address_test.go | 224 ++++++++++++++++---------- common/net/destination_test.go | 65 +++++--- testing/scenarios/common.go | 33 ++++ testing/scenarios/shadowsocks_test.go | 99 ++---------- testing/scenarios/vmess_test.go | 193 ++-------------------- 6 files changed, 246 insertions(+), 375 deletions(-) diff --git a/app/proxyman/outbound/handler_test.go b/app/proxyman/outbound/handler_test.go index d0edde503..25906f17a 100644 --- a/app/proxyman/outbound/handler_test.go +++ b/app/proxyman/outbound/handler_test.go @@ -5,12 +5,9 @@ import ( . "v2ray.com/core/app/proxyman/outbound" "v2ray.com/core/features/outbound" - . "v2ray.com/ext/assert" ) func TestInterfaces(t *testing.T) { - assert := With(t) - - assert((*Handler)(nil), Implements, (*outbound.Handler)(nil)) - assert((*Manager)(nil), Implements, (*outbound.Manager)(nil)) + _ = (outbound.Handler)(new(Handler)) + _ = (outbound.Manager)(new(Manager)) } diff --git a/common/net/address_test.go b/common/net/address_test.go index b3ed49497..5c8ed57ba 100644 --- a/common/net/address_test.go +++ b/common/net/address_test.go @@ -4,102 +4,158 @@ import ( "net" "testing" + "github.com/google/go-cmp/cmp" + . "v2ray.com/core/common/net" - . "v2ray.com/core/common/net/testing" - . "v2ray.com/ext/assert" ) -func TestIPv4Address(t *testing.T) { - assert := With(t) - - ip := []byte{byte(1), byte(2), byte(3), byte(4)} - addr := IPAddress(ip) - - assert(addr, IsIPv4) - assert(addr, Not(IsIPv6)) - assert(addr, Not(IsDomain)) - assert([]byte(addr.IP()), Equals, ip) - assert(addr.String(), Equals, "1.2.3.4") -} - -func TestIPv6Address(t *testing.T) { - assert := With(t) - - ip := []byte{ - byte(1), byte(2), byte(3), byte(4), - byte(1), byte(2), byte(3), byte(4), - byte(1), byte(2), byte(3), byte(4), - byte(1), byte(2), byte(3), byte(4), +func TestAddressProperty(t *testing.T) { + type addrProprty struct { + IP []byte + Domain string + Family AddressFamily + String string } - addr := IPAddress(ip) - assert(addr, IsIPv6) - assert(addr, Not(IsIPv4)) - assert(addr, Not(IsDomain)) - assert(addr.IP(), Equals, net.IP(ip)) - assert(addr.String(), Equals, "[102:304:102:304:102:304:102:304]") -} - -func TestIPv4Asv6(t *testing.T) { - assert := With(t) - ip := []byte{ - byte(0), byte(0), byte(0), byte(0), - byte(0), byte(0), byte(0), byte(0), - byte(0), byte(0), byte(255), byte(255), - byte(1), byte(2), byte(3), byte(4), + testCases := []struct { + Input Address + Output addrProprty + }{ + { + Input: IPAddress([]byte{byte(1), byte(2), byte(3), byte(4)}), + Output: addrProprty{ + IP: []byte{byte(1), byte(2), byte(3), byte(4)}, + Family: AddressFamilyIPv4, + String: "1.2.3.4", + }, + }, + { + Input: IPAddress([]byte{ + byte(1), byte(2), byte(3), byte(4), + byte(1), byte(2), byte(3), byte(4), + byte(1), byte(2), byte(3), byte(4), + byte(1), byte(2), byte(3), byte(4), + }), + Output: addrProprty{ + IP: []byte{ + byte(1), byte(2), byte(3), byte(4), + byte(1), byte(2), byte(3), byte(4), + byte(1), byte(2), byte(3), byte(4), + byte(1), byte(2), byte(3), byte(4), + }, + Family: AddressFamilyIPv6, + String: "[102:304:102:304:102:304:102:304]", + }, + }, + { + Input: IPAddress([]byte{ + byte(0), byte(0), byte(0), byte(0), + byte(0), byte(0), byte(0), byte(0), + byte(0), byte(0), byte(255), byte(255), + byte(1), byte(2), byte(3), byte(4), + }), + Output: addrProprty{ + IP: []byte{byte(1), byte(2), byte(3), byte(4)}, + Family: AddressFamilyIPv4, + String: "1.2.3.4", + }, + }, + { + Input: DomainAddress("v2ray.com"), + Output: addrProprty{ + Domain: "v2ray.com", + Family: AddressFamilyDomain, + String: "v2ray.com", + }, + }, + { + Input: IPAddress(net.IPv4(1, 2, 3, 4)), + Output: addrProprty{ + IP: []byte{byte(1), byte(2), byte(3), byte(4)}, + Family: AddressFamilyIPv4, + String: "1.2.3.4", + }, + }, + { + Input: ParseAddress("[2001:4860:0:2001::68]"), + Output: addrProprty{ + IP: []byte{0x20, 0x01, 0x48, 0x60, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68}, + Family: AddressFamilyIPv6, + String: "[2001:4860:0:2001::68]", + }, + }, + { + Input: ParseAddress("[::ffff:123.151.71.143]"), + Output: addrProprty{ + IP: []byte{123, 151, 71, 143}, + Family: AddressFamilyIPv4, + String: "123.151.71.143", + }, + }, + { + Input: NewIPOrDomain(ParseAddress("v2ray.com")).AsAddress(), + Output: addrProprty{ + Domain: "v2ray.com", + Family: AddressFamilyDomain, + String: "v2ray.com", + }, + }, + { + Input: NewIPOrDomain(ParseAddress("8.8.8.8")).AsAddress(), + Output: addrProprty{ + IP: []byte{8, 8, 8, 8}, + Family: AddressFamilyIPv4, + String: "8.8.8.8", + }, + }, + { + Input: NewIPOrDomain(ParseAddress("[2001:4860:0:2001::68]")).AsAddress(), + Output: addrProprty{ + IP: []byte{0x20, 0x01, 0x48, 0x60, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68}, + Family: AddressFamilyIPv6, + String: "[2001:4860:0:2001::68]", + }, + }, } - addr := IPAddress(ip) - assert(addr.String(), Equals, "1.2.3.4") -} -func TestDomainAddress(t *testing.T) { - assert := With(t) + for _, testCase := range testCases { + actual := addrProprty{ + Family: testCase.Input.Family(), + String: testCase.Input.String(), + } + if testCase.Input.Family().IsIP() { + actual.IP = testCase.Input.IP() + } else { + actual.Domain = testCase.Input.Domain() + } - domain := "v2ray.com" - addr := DomainAddress(domain) - - assert(addr, IsDomain) - assert(addr, Not(IsIPv6)) - assert(addr, Not(IsIPv4)) - assert(addr.Domain(), Equals, domain) - assert(addr.String(), Equals, "v2ray.com") -} - -func TestNetIPv4Address(t *testing.T) { - assert := With(t) - - ip := net.IPv4(1, 2, 3, 4) - addr := IPAddress(ip) - assert(addr, IsIPv4) - assert(addr.String(), Equals, "1.2.3.4") -} - -func TestParseIPv6Address(t *testing.T) { - assert := With(t) - - ip := ParseAddress("[2001:4860:0:2001::68]") - assert(ip, IsIPv6) - assert(ip.String(), Equals, "[2001:4860:0:2001::68]") - - ip = ParseAddress("[::ffff:123.151.71.143]") - assert(ip, IsIPv4) - assert(ip.String(), Equals, "123.151.71.143") + if r := cmp.Diff(actual, testCase.Output); r != "" { + t.Error("for input: ", testCase.Input, ":", r) + } + } } func TestInvalidAddressConvertion(t *testing.T) { - assert := With(t) + panics := func(f func()) (ret bool) { + defer func() { + if r := recover(); r != nil { + ret = true + } + }() + f() + return false + } - assert(func() { ParseAddress("8.8.8.8").Domain() }, Panics) - assert(func() { ParseAddress("2001:4860:0:2001::68").Domain() }, Panics) - assert(func() { ParseAddress("v2ray.com").IP() }, Panics) -} - -func TestIPOrDomain(t *testing.T) { - assert := With(t) - - assert(NewIPOrDomain(ParseAddress("v2ray.com")).AsAddress(), Equals, ParseAddress("v2ray.com")) - assert(NewIPOrDomain(ParseAddress("8.8.8.8")).AsAddress(), Equals, ParseAddress("8.8.8.8")) - assert(NewIPOrDomain(ParseAddress("2001:4860:0:2001::68")).AsAddress(), Equals, ParseAddress("2001:4860:0:2001::68")) + testCases := []func(){ + func() { ParseAddress("8.8.8.8").Domain() }, + func() { ParseAddress("2001:4860:0:2001::68").Domain() }, + func() { ParseAddress("v2ray.com").IP() }, + } + for idx, testCase := range testCases { + if !panics(testCase) { + t.Error("case ", idx, " failed") + } + } } func BenchmarkParseAddressIPv4(b *testing.B) { diff --git a/common/net/destination_test.go b/common/net/destination_test.go index 8c9cd9ade..3cfe915b9 100644 --- a/common/net/destination_test.go +++ b/common/net/destination_test.go @@ -3,32 +3,47 @@ package net_test import ( "testing" + "github.com/google/go-cmp/cmp" + . "v2ray.com/core/common/net" - . "v2ray.com/core/common/net/testing" - . "v2ray.com/ext/assert" ) -func TestTCPDestination(t *testing.T) { - assert := With(t) +func TestDestinationProperty(t *testing.T) { + testCases := []struct { + Input Destination + Network Network + String string + NetString string + }{ + { + Input: TCPDestination(IPAddress([]byte{1, 2, 3, 4}), 80), + Network: Network_TCP, + String: "tcp:1.2.3.4:80", + NetString: "1.2.3.4:80", + }, + { + Input: UDPDestination(IPAddress([]byte{0x20, 0x01, 0x48, 0x60, 0x48, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88}), 53), + Network: Network_UDP, + String: "udp:[2001:4860:4860::8888]:53", + NetString: "[2001:4860:4860::8888]:53", + }, + } - dest := TCPDestination(IPAddress([]byte{1, 2, 3, 4}), 80) - assert(dest, IsTCP) - assert(dest, Not(IsUDP)) - assert(dest.String(), Equals, "tcp:1.2.3.4:80") -} - -func TestUDPDestination(t *testing.T) { - assert := With(t) - - dest := UDPDestination(IPAddress([]byte{0x20, 0x01, 0x48, 0x60, 0x48, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88}), 53) - assert(dest, Not(IsTCP)) - assert(dest, IsUDP) - assert(dest.String(), Equals, "udp:[2001:4860:4860::8888]:53") + for _, testCase := range testCases { + dest := testCase.Input + if r := cmp.Diff(dest.Network, testCase.Network); r != "" { + t.Error("unexpected Network in ", dest.String(), ": ", r) + } + if r := cmp.Diff(dest.String(), testCase.String); r != "" { + t.Error(r) + } + if r := cmp.Diff(dest.NetAddr(), testCase.NetString); r != "" { + t.Error(r) + } + } } func TestDestinationParse(t *testing.T) { - assert := With(t) - cases := []struct { Input string Output Destination @@ -69,10 +84,16 @@ func TestDestinationParse(t *testing.T) { for _, testcase := range cases { d, err := ParseDestination(testcase.Input) if !testcase.Error { - assert(err, IsNil) - assert(d, Equals, testcase.Output) + if err != nil { + t.Error("for test case: ", testcase.Input, " expected no error, but got ", err) + } + if d != testcase.Output { + t.Error("for test case: ", testcase.Input, " expected output: ", testcase.Output.String(), " but got ", d.String()) + } } else { - assert(err, IsNotNil) + if err == nil { + t.Error("for test case: ", testcase.Input, " expected error, but got nil") + } } } } diff --git a/testing/scenarios/common.go b/testing/scenarios/common.go index 98b94eab7..5875ab43e 100644 --- a/testing/scenarios/common.go +++ b/testing/scenarios/common.go @@ -1,6 +1,7 @@ package scenarios import ( + "crypto/rand" "fmt" "io" "io/ioutil" @@ -12,10 +13,12 @@ import ( "time" "github.com/golang/protobuf/proto" + "github.com/google/go-cmp/cmp" "v2ray.com/core" "v2ray.com/core/app/dispatcher" "v2ray.com/core/app/proxyman" "v2ray.com/core/common" + "v2ray.com/core/common/errors" "v2ray.com/core/common/log" "v2ray.com/core/common/net" "v2ray.com/core/common/retry" @@ -134,3 +137,33 @@ func withDefaultApps(config *core.Config) *core.Config { config.App = append(config.App, serial.ToTypedMessage(&proxyman.OutboundConfig{})) return config } + +func testTCPConn(port net.Port, payloadSize int, timeout time.Duration) func() error { + return func() error { + conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ + IP: []byte{127, 0, 0, 1}, + Port: int(port), + }) + if err != nil { + return err + } + defer conn.Close() + + payload := make([]byte, payloadSize) + common.Must2(rand.Read(payload)) + + nBytes, err := conn.Write(payload) + if err != nil { + return err + } + if nBytes != len(payload) { + return errors.New("expect ", len(payload), " written, but actually ", nBytes) + } + + response := readFrom(conn, timeout, payloadSize) + if r := cmp.Diff(response, xor(payload)); r != "" { + return errors.New(r) + } + return nil + } +} diff --git a/testing/scenarios/shadowsocks_test.go b/testing/scenarios/shadowsocks_test.go index ac046088f..211e460ad 100644 --- a/testing/scenarios/shadowsocks_test.go +++ b/testing/scenarios/shadowsocks_test.go @@ -118,33 +118,7 @@ func TestShadowsocksAES256TCP(t *testing.T) { var errg errgroup.Group for i := 0; i < 10; i++ { - errg.Go(func() error { - conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ - IP: []byte{127, 0, 0, 1}, - Port: int(clientPort), - }) - if err != nil { - return err - } - defer conn.Close() - - payload := make([]byte, 10240*1024) - common.Must2(rand.Read(payload)) - - nBytes, err := conn.Write([]byte(payload)) - if err != nil { - return err - } - if nBytes != len(payload) { - return errors.New("expect ", len(payload), " written, but actually ", nBytes) - } - - response := readFrom(conn, time.Second*20, 10240*1024) - if r := cmp.Diff(response, xor([]byte(payload))); r != "" { - return errors.New(r) - } - return nil - }) + errg.Go(testTCPConn(clientPort, 10240*1024, time.Second*20)) } if err := errg.Wait(); err != nil { t.Fatal(err) @@ -278,7 +252,6 @@ func TestShadowsocksAES128UDP(t *testing.T) { } func TestShadowsocksChacha20TCP(t *testing.T) { - tcpServer := tcp.Server{ MsgProcessor: xor, } @@ -367,39 +340,16 @@ func TestShadowsocksChacha20TCP(t *testing.T) { servers, err := InitializeServerConfigs(serverConfig, clientConfig) common.Must(err) - defer CloseAllServers(servers) - var wg sync.WaitGroup - wg.Add(10) + var errg errgroup.Group for i := 0; i < 10; i++ { - go func() { - defer wg.Done() - - conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ - IP: []byte{127, 0, 0, 1}, - Port: int(clientPort), - }) - common.Must(err) - defer conn.Close() - - payload := make([]byte, 10240*1024) - rand.Read(payload) - - nBytes, err := conn.Write([]byte(payload)) - common.Must(err) - - if nBytes != len(payload) { - t.Error("only part of payload is written: ", nBytes) - } - - response := readFrom(conn, time.Second*20, 10240*1024) - if r := cmp.Diff(response, xor([]byte(payload))); r != "" { - t.Error(r) - } - }() + errg.Go(testTCPConn(clientPort, 10240*1024, time.Second*20)) + } + + if err := errg.Wait(); err != nil { + t.Error(err) } - wg.Wait() } func TestShadowsocksChacha20Poly1305TCP(t *testing.T) { @@ -408,7 +358,6 @@ func TestShadowsocksChacha20Poly1305TCP(t *testing.T) { } dest, err := tcpServer.Start() common.Must(err) - defer tcpServer.Close() account := serial.ToTypedMessage(&shadowsocks.Account{ @@ -478,39 +427,15 @@ func TestShadowsocksChacha20Poly1305TCP(t *testing.T) { servers, err := InitializeServerConfigs(serverConfig, clientConfig) common.Must(err) - defer CloseAllServers(servers) - var wg sync.WaitGroup - wg.Add(10) + var errg errgroup.Group for i := 0; i < 10; i++ { - go func() { - defer wg.Done() - - conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ - IP: []byte{127, 0, 0, 1}, - Port: int(clientPort), - }) - common.Must(err) - defer conn.Close() - - payload := make([]byte, 10240*1024) - rand.Read(payload) - - nBytes, err := conn.Write([]byte(payload)) - common.Must(err) - - if nBytes != len(payload) { - t.Error("only part of payload is written: ", nBytes) - } - - response := readFrom(conn, time.Second*20, 10240*1024) - if r := cmp.Diff(response, xor([]byte(payload))); r != "" { - t.Error(r) - } - }() + errg.Go(testTCPConn(clientPort, 10240*1024, time.Second*20)) + } + if err := errg.Wait(); err != nil { + t.Error(err) } - wg.Wait() } func TestShadowsocksAES256GCMTCP(t *testing.T) { diff --git a/testing/scenarios/vmess_test.go b/testing/scenarios/vmess_test.go index 46f98784d..82c62a680 100644 --- a/testing/scenarios/vmess_test.go +++ b/testing/scenarios/vmess_test.go @@ -8,6 +8,7 @@ import ( "time" "github.com/google/go-cmp/cmp" + "golang.org/x/sync/errgroup" "v2ray.com/core" "v2ray.com/core/app/log" "v2ray.com/core/app/proxyman" @@ -943,13 +944,11 @@ func TestVMessKCP(t *testing.T) { } func TestVMessKCPLarge(t *testing.T) { - assert := With(t) - tcpServer := tcp.Server{ MsgProcessor: xor, } dest, err := tcpServer.Start() - assert(err, IsNil) + common.Must(err) defer tcpServer.Close() userID := protocol.NewID(uuid.New()) @@ -1081,163 +1080,24 @@ func TestVMessKCPLarge(t *testing.T) { } servers, err := InitializeServerConfigs(serverConfig, clientConfig) - assert(err, IsNil) + common.Must(err) defer CloseAllServers(servers) - var wg sync.WaitGroup + var errg errgroup.Group for i := 0; i < 2; i++ { - wg.Add(1) - go func() { - defer wg.Done() - - conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ - IP: []byte{127, 0, 0, 1}, - Port: int(clientPort), - }) - assert(err, IsNil) - defer conn.Close() - - payload := make([]byte, 10240*1024) - rand.Read(payload) - - nBytes, err := conn.Write(payload) - assert(err, IsNil) - assert(nBytes, Equals, len(payload)) - - response := readFrom(conn, time.Minute*10, 10240*1024) - if r := cmp.Diff(response, xor(payload)); r != "" { - t.Error(r) - } - }() + errg.Go(testTCPConn(clientPort, 10240*1024, time.Minute*5)) } - wg.Wait() -} - -func TestVMessIPv6(t *testing.T) { - t.SkipNow() // No IPv6 on travis-ci. - assert := With(t) - - tcpServer := tcp.Server{ - MsgProcessor: xor, - Listen: net.LocalHostIPv6, + if err := errg.Wait(); err != nil { + t.Error(err) } - dest, err := tcpServer.Start() - assert(err, IsNil) - defer tcpServer.Close() - - userID := protocol.NewID(uuid.New()) - serverPort := tcp.PickPort() - serverConfig := &core.Config{ - App: []*serial.TypedMessage{ - serial.ToTypedMessage(&log.Config{ - ErrorLogLevel: clog.Severity_Debug, - ErrorLogType: log.LogType_Console, - }), - }, - Inbound: []*core.InboundHandlerConfig{ - { - ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ - PortRange: net.SinglePortRange(serverPort), - Listen: net.NewIPOrDomain(net.LocalHostIPv6), - }), - ProxySettings: serial.ToTypedMessage(&inbound.Config{ - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - AlterId: 64, - }), - }, - }, - }), - }, - }, - Outbound: []*core.OutboundHandlerConfig{ - { - ProxySettings: serial.ToTypedMessage(&freedom.Config{}), - }, - }, - } - - clientPort := tcp.PickPort() - clientConfig := &core.Config{ - App: []*serial.TypedMessage{ - serial.ToTypedMessage(&log.Config{ - ErrorLogLevel: clog.Severity_Debug, - ErrorLogType: log.LogType_Console, - }), - }, - Inbound: []*core.InboundHandlerConfig{ - { - ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ - PortRange: net.SinglePortRange(clientPort), - Listen: net.NewIPOrDomain(net.LocalHostIPv6), - }), - ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ - Address: net.NewIPOrDomain(dest.Address), - Port: uint32(dest.Port), - NetworkList: &net.NetworkList{ - Network: []net.Network{net.Network_TCP}, - }, - }), - }, - }, - Outbound: []*core.OutboundHandlerConfig{ - { - ProxySettings: serial.ToTypedMessage(&outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ - { - Address: net.NewIPOrDomain(net.LocalHostIPv6), - Port: uint32(serverPort), - User: []*protocol.User{ - { - Account: serial.ToTypedMessage(&vmess.Account{ - Id: userID.String(), - AlterId: 64, - SecuritySettings: &protocol.SecurityConfig{ - Type: protocol.SecurityType_AES128_GCM, - }, - }), - }, - }, - }, - }, - }), - }, - }, - } - - servers, err := InitializeServerConfigs(serverConfig, clientConfig) - assert(err, IsNil) - - conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ - IP: net.LocalHostIPv6.IP(), - Port: int(clientPort), - }) - assert(err, IsNil) - - payload := make([]byte, 1024) - rand.Read(payload) - - nBytes, err := conn.Write(payload) - assert(err, IsNil) - assert(nBytes, Equals, len(payload)) - - response := readFrom(conn, time.Second*20, 1024) - assert(response, Equals, xor(payload)) - assert(conn.Close(), IsNil) - - CloseAllServers(servers) } func TestVMessGCMMux(t *testing.T) { - assert := With(t) - tcpServer := tcp.Server{ MsgProcessor: xor, } dest, err := tcpServer.Start() - assert(err, IsNil) + common.Must(err) defer tcpServer.Close() userID := protocol.NewID(uuid.New()) @@ -1329,40 +1189,19 @@ func TestVMessGCMMux(t *testing.T) { } servers, err := InitializeServerConfigs(serverConfig, clientConfig) - assert(err, IsNil) + common.Must(err) + defer CloseAllServers(servers) for range "abcd" { - var wg sync.WaitGroup - const nConnection = 16 - wg.Add(nConnection) - for i := 0; i < nConnection; i++ { - go func() { - conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ - IP: []byte{127, 0, 0, 1}, - Port: int(clientPort), - }) - assert(err, IsNil) - - payload := make([]byte, 10240) - rand.Read(payload) - - xorpayload := xor(payload) - - nBytes, err := conn.Write(payload) - assert(err, IsNil) - assert(nBytes, Equals, len(payload)) - - response := readFrom(conn, time.Second*20, 10240) - assert(response, Equals, xorpayload) - assert(conn.Close(), IsNil) - wg.Done() - }() + var errg errgroup.Group + for i := 0; i < 16; i++ { + errg.Go(testTCPConn(clientPort, 10240, time.Second*20)) + } + if err := errg.Wait(); err != nil { + t.Fatal(err) } - wg.Wait() time.Sleep(time.Second) } - - CloseAllServers(servers) } func TestVMessGCMMuxUDP(t *testing.T) {