test: verify request overload recovery

This commit is contained in:
2026-09-22 14:57:25 +08:00
parent 8e474a24d9
commit b7dc36fc99
3 changed files with 79 additions and 0 deletions

View File

@@ -722,6 +722,83 @@ func TestServerConcurrentRequestLimit(t *testing.T) {
}
}
func TestServerConcurrentRequestLimitRecovers(t *testing.T) {
started := make(chan struct{})
release := make(chan struct{})
var first sync.Once
application := omni.NewWithRouter(netrouter.New())
application.GET("/work", func(ctx *omni.Context) error {
first.Do(func() {
close(started)
<-release
})
return ctx.OK("done")
})
server := native.New(application)
server.MaxConcurrentRequests = 1
listener, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatal(err)
}
done := make(chan error, 1)
go func() { done <- server.Serve(context.Background(), listener) }()
waitForServer(t, listener.Addr().String())
defer stopServer(t, server, listener, done)
firstConn, err := net.Dial("tcp", listener.Addr().String())
if err != nil {
t.Fatal(err)
}
defer firstConn.Close()
_, _ = io.WriteString(firstConn, "GET /work HTTP/1.1\r\nHost: test\r\nConnection: close\r\n\r\n")
select {
case <-started:
case <-time.After(2 * time.Second):
t.Fatal("first handler did not start")
}
secondConn, err := net.Dial("tcp", listener.Addr().String())
if err != nil {
t.Fatal(err)
}
_, _ = io.WriteString(secondConn, "GET /work HTTP/1.1\r\nHost: test\r\nConnection: close\r\n\r\n")
response, err := http.ReadResponse(bufio.NewReader(secondConn), &http.Request{Method: http.MethodGet})
if err != nil {
secondConn.Close()
t.Fatal(err)
}
response.Body.Close()
secondConn.Close()
if response.StatusCode != http.StatusServiceUnavailable {
t.Fatalf("expected 503 at concurrency limit, got %d", response.StatusCode)
}
close(release)
response, err = http.ReadResponse(bufio.NewReader(firstConn), &http.Request{Method: http.MethodGet})
if err != nil {
t.Fatal(err)
}
response.Body.Close()
if response.StatusCode != http.StatusOK {
t.Fatalf("expected held request to complete, got %d", response.StatusCode)
}
thirdConn, err := net.Dial("tcp", listener.Addr().String())
if err != nil {
t.Fatal(err)
}
defer thirdConn.Close()
_, _ = io.WriteString(thirdConn, "GET /work HTTP/1.1\r\nHost: test\r\nConnection: close\r\n\r\n")
response, err = http.ReadResponse(bufio.NewReader(thirdConn), &http.Request{Method: http.MethodGet})
if err != nil {
t.Fatal(err)
}
response.Body.Close()
if response.StatusCode != http.StatusOK {
t.Fatalf("request slot was not reusable after overload, got %d", response.StatusCode)
}
}
func TestServerConnectionLimitReleasesAfterRequest(t *testing.T) {
started := make(chan struct{})
release := make(chan struct{})