starnet/timeout_refactor_test.go
starainrt b5bd7595a1
1. 优化ping功能
2. 新增重试机制
3. 优化错误处理逻辑
2026-03-19 16:42:45 +08:00

116 lines
2.8 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package starnet
import (
"io"
"net"
"net/http"
"net/http/httptest"
"testing"
"time"
)
func TestRequestTimeoutDoesNotMutateClientTimeout(t *testing.T) {
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
time.Sleep(200 * time.Millisecond)
w.WriteHeader(http.StatusOK)
}))
defer s.Close()
client := NewClientNoErr()
baseTimeout := client.HTTPClient().Timeout
_, err := client.Get(s.URL, WithTimeout(80*time.Millisecond))
if err == nil {
t.Fatal("expected request timeout error")
}
if client.HTTPClient().Timeout != baseTimeout {
t.Fatalf("client timeout mutated: got=%v want=%v", client.HTTPClient().Timeout, baseTimeout)
}
resp, err := client.Get(s.URL, WithTimeout(400*time.Millisecond))
if err != nil {
t.Fatalf("second request should succeed with larger timeout: %v", err)
}
defer resp.Close()
}
func TestRequestTimeoutNoLingeringConnDeadline(t *testing.T) {
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, _ = io.Copy(io.Discard, r.Body)
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("ok"))
}))
defer s.Close()
client := NewClientNoErr()
resp1, err := client.Post(s.URL, WithBodyString("first"), WithTimeout(120*time.Millisecond))
if err != nil {
t.Fatalf("first request should succeed: %v", err)
}
_ = resp1.Close()
// 如果请求超时依赖连接级绝对 deadline经过该等待后复用连接会出现误超时。
time.Sleep(220 * time.Millisecond)
resp2, err := client.Post(s.URL, WithBodyString("second"), WithTimeout(1*time.Second))
if err != nil {
t.Fatalf("second request should not be affected by previous timeout window: %v", err)
}
_ = resp2.Close()
}
func TestConnReadDeadlineTimeoutAndRecover(t *testing.T) {
ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatalf("listen error: %v", err)
}
defer ln.Close()
done := make(chan struct{})
go func() {
defer close(done)
conn, err := ln.Accept()
if err != nil {
return
}
defer conn.Close()
time.Sleep(180 * time.Millisecond)
_, _ = conn.Write([]byte("x"))
}()
c, err := Dial("tcp", ln.Addr().String())
if err != nil {
t.Fatalf("dial error: %v", err)
}
defer c.Close()
if err := c.SetReadDeadline(time.Now().Add(60 * time.Millisecond)); err != nil {
t.Fatalf("set read deadline error: %v", err)
}
buf := make([]byte, 1)
_, err = c.Read(buf)
if err == nil {
t.Fatal("expected read timeout error")
}
if ne, ok := err.(net.Error); !ok || !ne.Timeout() {
t.Fatalf("expected net timeout error, got: %v", err)
}
if err := c.SetReadDeadline(time.Time{}); err != nil {
t.Fatalf("clear read deadline error: %v", err)
}
if _, err := io.ReadFull(c, buf); err != nil {
t.Fatalf("read after clearing deadline should succeed: %v", err)
}
if string(buf) != "x" {
t.Fatalf("unexpected payload: %q", string(buf))
}
<-done
}