mirror of
https://github.com/fatedier/frp.git
synced 2026-07-24 04:49:18 +08:00
96 lines
2.2 KiB
Go
96 lines
2.2 KiB
Go
package client
|
|
|
|
import (
|
|
"context"
|
|
"net"
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/fatedier/frp/client/proxy"
|
|
"github.com/fatedier/frp/client/visitor"
|
|
v1 "github.com/fatedier/frp/pkg/config/v1"
|
|
"github.com/fatedier/frp/pkg/msg"
|
|
)
|
|
|
|
type gracefulCloseTestConnector struct {
|
|
conn net.Conn
|
|
}
|
|
|
|
func (*gracefulCloseTestConnector) Connect() (*msg.Conn, error) { return nil, net.ErrClosed }
|
|
func (c *gracefulCloseTestConnector) Close() error { return c.conn.Close() }
|
|
|
|
func newGracefulCloseTestService() *Service {
|
|
ctx := context.Background()
|
|
common := &v1.ClientCommonConfig{}
|
|
serverConn, clientConn := net.Pipe()
|
|
ctl := &Control{
|
|
ctx: ctx,
|
|
sessionCtx: &SessionContext{
|
|
Common: common,
|
|
RunID: "graceful-close-race",
|
|
Conn: msg.NewConn(clientConn, msg.NewV1ReadWriter(clientConn)),
|
|
Connector: &gracefulCloseTestConnector{conn: serverConn},
|
|
},
|
|
doneCh: make(chan struct{}),
|
|
}
|
|
ctl.pm = proxy.NewManager(ctx, common, nil, nil, nil)
|
|
ctl.vm = visitor.NewManager(ctx, "graceful-close-race", common, nil, nil, nil)
|
|
return &Service{ctl: ctl, cancel: context.CancelCauseFunc(func(error) {})}
|
|
}
|
|
|
|
func TestGracefulCloseAndStopSynchronizeDuration(t *testing.T) {
|
|
for i := range 10000 {
|
|
svr := newGracefulCloseTestService()
|
|
start := make(chan struct{})
|
|
var wg sync.WaitGroup
|
|
wg.Add(2)
|
|
go func() {
|
|
defer wg.Done()
|
|
<-start
|
|
svr.GracefulClose(time.Duration(i))
|
|
}()
|
|
go func() {
|
|
defer wg.Done()
|
|
<-start
|
|
svr.stop()
|
|
}()
|
|
close(start)
|
|
wg.Wait()
|
|
}
|
|
}
|
|
|
|
func TestGracefulCloseDoesNotBlockDuringStop(t *testing.T) {
|
|
const gracefulDuration = 200 * time.Millisecond
|
|
|
|
svr := newGracefulCloseTestService()
|
|
svr.GracefulClose(gracefulDuration)
|
|
stopDone := make(chan struct{})
|
|
go func() {
|
|
svr.stop()
|
|
close(stopDone)
|
|
}()
|
|
defer func() {
|
|
select {
|
|
case <-stopDone:
|
|
case <-time.After(time.Second):
|
|
t.Error("stop did not finish")
|
|
}
|
|
}()
|
|
|
|
deadline := time.Now().Add(time.Second)
|
|
for svr.ctlMu.TryLock() {
|
|
svr.ctlMu.Unlock()
|
|
if time.Now().After(deadline) {
|
|
t.Fatal("stop did not acquire ctlMu")
|
|
}
|
|
time.Sleep(time.Millisecond)
|
|
}
|
|
|
|
start := time.Now()
|
|
svr.GracefulClose(0)
|
|
if elapsed := time.Since(start); elapsed >= gracefulDuration/2 {
|
|
t.Fatalf("GracefulClose blocked for %v while stop was waiting", elapsed)
|
|
}
|
|
}
|