112 lines
2.1 KiB
Go
112 lines
2.1 KiB
Go
|
|
package starnet
|
||
|
|
|
||
|
|
import (
|
||
|
|
"fmt"
|
||
|
|
"net/http"
|
||
|
|
"net/http/httptest"
|
||
|
|
"sync"
|
||
|
|
"sync/atomic"
|
||
|
|
"testing"
|
||
|
|
"time"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestConcurrentRequests(t *testing.T) {
|
||
|
|
var counter int64
|
||
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
|
|
atomic.AddInt64(&counter, 1)
|
||
|
|
w.WriteHeader(http.StatusOK)
|
||
|
|
w.Write([]byte("OK"))
|
||
|
|
}))
|
||
|
|
defer server.Close()
|
||
|
|
|
||
|
|
client := NewClientNoErr()
|
||
|
|
concurrency := 100
|
||
|
|
var wg sync.WaitGroup
|
||
|
|
wg.Add(concurrency)
|
||
|
|
|
||
|
|
for i := 0; i < concurrency; i++ {
|
||
|
|
go func() {
|
||
|
|
defer wg.Done()
|
||
|
|
resp, err := client.Get(server.URL)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("Get() error: %v", err)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
resp.Close()
|
||
|
|
}()
|
||
|
|
}
|
||
|
|
|
||
|
|
wg.Wait()
|
||
|
|
|
||
|
|
if atomic.LoadInt64(&counter) != int64(concurrency) {
|
||
|
|
t.Errorf("counter = %v; want %v", counter, concurrency)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestConcurrentClientModification(t *testing.T) {
|
||
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
|
|
w.WriteHeader(http.StatusOK)
|
||
|
|
}))
|
||
|
|
defer server.Close()
|
||
|
|
|
||
|
|
client := NewClientNoErr()
|
||
|
|
var wg sync.WaitGroup
|
||
|
|
wg.Add(200)
|
||
|
|
|
||
|
|
// 100 goroutines reading
|
||
|
|
for i := 0; i < 100; i++ {
|
||
|
|
go func() {
|
||
|
|
defer wg.Done()
|
||
|
|
resp, err := client.Get(server.URL)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("Get() error: %v", err)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
resp.Close()
|
||
|
|
}()
|
||
|
|
}
|
||
|
|
|
||
|
|
// 100 goroutines modifying options
|
||
|
|
for i := 0; i < 100; i++ {
|
||
|
|
go func(i int) {
|
||
|
|
defer wg.Done()
|
||
|
|
if i%2 == 0 {
|
||
|
|
client.AddOptions(WithTimeout(5 * time.Second))
|
||
|
|
} else {
|
||
|
|
_ = client.RequestOptions()
|
||
|
|
}
|
||
|
|
}(i)
|
||
|
|
}
|
||
|
|
|
||
|
|
wg.Wait()
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestConcurrentRequestClone(t *testing.T) {
|
||
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
|
|
w.WriteHeader(http.StatusOK)
|
||
|
|
}))
|
||
|
|
defer server.Close()
|
||
|
|
|
||
|
|
baseReq := NewSimpleRequest(server.URL, "GET").SetHeader("X-Base", "value")
|
||
|
|
|
||
|
|
var wg sync.WaitGroup
|
||
|
|
wg.Add(50)
|
||
|
|
|
||
|
|
for i := 0; i < 50; i++ {
|
||
|
|
go func(i int) {
|
||
|
|
defer wg.Done()
|
||
|
|
cloned := baseReq.Clone()
|
||
|
|
// 修复:使用有效的 header 值
|
||
|
|
cloned.SetHeader("X-Index", fmt.Sprintf("%d", i))
|
||
|
|
resp, err := cloned.Do()
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("Do() error: %v", err)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
resp.Close()
|
||
|
|
}(i)
|
||
|
|
}
|
||
|
|
|
||
|
|
wg.Wait()
|
||
|
|
}
|