starnet/timeout_refactor_test.go

116 lines
2.8 KiB
Go
Raw Normal View History

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
}