mirror of
https://github.com/libp2p/go-reuseport.git
synced 2025-10-05 14:56:51 +08:00
large test (+goselect)
This commit is contained in:
@@ -8,8 +8,3 @@ import (
|
|||||||
|
|
||||||
var soReusePort = syscall.SO_REUSEPORT
|
var soReusePort = syscall.SO_REUSEPORT
|
||||||
var soReuseAddr = syscall.SO_REUSEADDR
|
var soReuseAddr = syscall.SO_REUSEADDR
|
||||||
|
|
||||||
func Select(nfd int, r *syscall.FdSet, w *syscall.FdSet, e *syscall.FdSet, timeout *syscall.Timeval) (n int, err error) {
|
|
||||||
err = syscall.Select(nfd, r, w, e, timeout)
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
@@ -8,7 +8,3 @@ import (
|
|||||||
|
|
||||||
var soReusePort = 15 // this is not defined in unix go pkg.
|
var soReusePort = 15 // this is not defined in unix go pkg.
|
||||||
var soReuseAddr = syscall.SO_REUSEADDR
|
var soReuseAddr = syscall.SO_REUSEADDR
|
||||||
|
|
||||||
func Select(nfd int, r *syscall.FdSet, w *syscall.FdSet, e *syscall.FdSet, timeout *syscall.Timeval) (n int, err error) {
|
|
||||||
return syscall.Select(nfd, r, w, e, timeout)
|
|
||||||
}
|
|
||||||
|
21
impl_unix.go
21
impl_unix.go
@@ -3,7 +3,6 @@
|
|||||||
package reuseport
|
package reuseport
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -11,6 +10,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
sockaddrnet "github.com/jbenet/go-sockaddr/net"
|
sockaddrnet "github.com/jbenet/go-sockaddr/net"
|
||||||
|
goselect "github.com/jbenet/goselect"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -324,18 +324,18 @@ func connect(fd int, ra syscall.Sockaddr, deadline time.Time) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
var to *syscall.Timeval
|
var timeout time.Duration
|
||||||
var pw syscall.FdSet
|
var pw goselect.FDSet
|
||||||
FD_SET(uintptr(fd), &pw)
|
pw.Set(uintptr(fd))
|
||||||
for {
|
for {
|
||||||
// wait until the fd is ready to read or write.
|
// wait until the fd is ready to read or write.
|
||||||
if !deadline.IsZero() {
|
if !deadline.IsZero() {
|
||||||
to2 := syscall.NsecToTimeval(deadline.Sub(time.Now()).Nanoseconds())
|
timeout = deadline.Sub(time.Now())
|
||||||
to = &to2
|
} else {
|
||||||
|
timeout = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = Select(fd+1, nil, &pw, nil, to); err != nil {
|
if err = goselect.Select(fd+1, nil, &pw, nil, timeout); err != nil {
|
||||||
fmt.Println(err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,8 +373,3 @@ type timeoutError struct{}
|
|||||||
func (e *timeoutError) Error() string { return "i/o timeout" }
|
func (e *timeoutError) Error() string { return "i/o timeout" }
|
||||||
func (e *timeoutError) Timeout() bool { return true }
|
func (e *timeoutError) Timeout() bool { return true }
|
||||||
func (e *timeoutError) Temporary() bool { return true }
|
func (e *timeoutError) Temporary() bool { return true }
|
||||||
|
|
||||||
func FD_SET(fd uintptr, p *syscall.FdSet) {
|
|
||||||
n, k := fd/32, fd%32
|
|
||||||
p.Bits[n] |= (1 << uint32(k))
|
|
||||||
}
|
|
||||||
|
104
reuse_test.go
104
reuse_test.go
@@ -3,10 +3,12 @@ package reuseport
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -262,6 +264,108 @@ func TestStreamListenDialSamePort(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestStreamListenDialSamePortStressManyMsgs(t *testing.T) {
|
||||||
|
testCases := [][]string{
|
||||||
|
[]string{"tcp", "127.0.0.1:0"},
|
||||||
|
[]string{"tcp4", "127.0.0.1:0"},
|
||||||
|
[]string{"tcp6", "[::]:0"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tcase := range testCases {
|
||||||
|
subestStreamListenDialSamePortStress(t, tcase[0], tcase[1], 2, 100)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStreamListenDialSamePortStressManyNodes(t *testing.T) {
|
||||||
|
testCases := [][]string{
|
||||||
|
[]string{"tcp", "127.0.0.1:0"},
|
||||||
|
[]string{"tcp4", "127.0.0.1:0"},
|
||||||
|
[]string{"tcp6", "[::]:0"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tcase := range testCases {
|
||||||
|
subestStreamListenDialSamePortStress(t, tcase[0], tcase[1], 100, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func subestStreamListenDialSamePortStress(t *testing.T, network, addr string, nodes int, msgs int) {
|
||||||
|
t.Logf("testing %s:%s %d nodes %d msgs", network, addr, nodes, msgs)
|
||||||
|
|
||||||
|
var ls []net.Listener
|
||||||
|
for i := 0; i < nodes; i++ {
|
||||||
|
l, err := Listen(network, addr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer l.Close()
|
||||||
|
go acceptAndEcho(l)
|
||||||
|
ls = append(ls, l)
|
||||||
|
t.Logf("listening %s", l.Addr())
|
||||||
|
}
|
||||||
|
|
||||||
|
// connect them all
|
||||||
|
var cs []net.Conn
|
||||||
|
for i := 0; i < nodes; i++ {
|
||||||
|
for j := 0; j < i; j++ {
|
||||||
|
if i == j {
|
||||||
|
continue // cannot do self.
|
||||||
|
}
|
||||||
|
|
||||||
|
ia := ls[i].Addr().String()
|
||||||
|
ja := ls[j].Addr().String()
|
||||||
|
c, err := Dial(network, ia, ja)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(network, ia, ja, err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
cs = append(cs, c)
|
||||||
|
t.Logf("dialed %s --> %s", c.LocalAddr(), c.RemoteAddr())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errs := make(chan error)
|
||||||
|
|
||||||
|
send := func(c net.Conn, buf []byte) {
|
||||||
|
if _, err := c.Write(buf); err != nil {
|
||||||
|
errs <- err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
recv := func(c net.Conn, buf []byte) {
|
||||||
|
buf2 := make([]byte, len(buf))
|
||||||
|
if _, err := c.Read(buf2); err != nil {
|
||||||
|
errs <- err
|
||||||
|
}
|
||||||
|
if !bytes.Equal(buf, buf2) {
|
||||||
|
errs <- fmt.Errorf("recv failure: %s <--> %s -- %s %s", c.RemoteAddr(), c.LocalAddr(), buf, buf2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Logf("sending %d msgs per conn", msgs)
|
||||||
|
go func() {
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for _, c := range cs {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(c net.Conn) {
|
||||||
|
defer wg.Done()
|
||||||
|
for i := 0; i < msgs; i++ {
|
||||||
|
msg := []byte(fmt.Sprintf("message %d", i))
|
||||||
|
send(c, msg)
|
||||||
|
recv(c, msg)
|
||||||
|
}
|
||||||
|
}(c)
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
close(errs)
|
||||||
|
}()
|
||||||
|
|
||||||
|
for err := range errs {
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestPacketListenDialSamePort(t *testing.T) {
|
func TestPacketListenDialSamePort(t *testing.T) {
|
||||||
|
|
||||||
any := [][]string{
|
any := [][]string{
|
||||||
|
Reference in New Issue
Block a user