starnet/benchmark_test.go
starainrt 732e81316c
fix(starnet): 重构请求执行链路并补齐代理/重试/trace边界
- 分离 Request 的配置态与执行态,修复二次 Do、raw 模式网络配置失效和 body 来源互斥问题
  - 新增 starnet trace 抽象,补齐 DNS/连接/TLS/重试事件,并优化动态 transport 缓存与代理解析路径
  - 收紧非法代理为 fail-fast,多目标目标回退仅限幂等请求,修复 Host/TLS/SNI 等语义边界
  - 补充防御性拷贝、专项回归测试、本地代理/TLS 用例与 README 行为说明
2026-04-19 15:39:51 +08:00

225 lines
4.6 KiB
Go

package starnet
import (
"fmt"
"net/http"
"net/http/httptest"
"testing"
)
func BenchmarkGetRequest(b *testing.B) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("OK"))
}))
defer server.Close()
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
resp, err := Get(server.URL)
if err != nil {
b.Fatalf("Get() error: %v", err)
}
resp.Body().String()
resp.Close()
}
}
func BenchmarkGetRequestWithHeaders(b *testing.B) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("OK"))
}))
defer server.Close()
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
resp, err := Get(server.URL,
WithHeader("X-Custom", "value"),
WithUserAgent("BenchmarkAgent"))
if err != nil {
b.Fatalf("Get() error: %v", err)
}
resp.Body().String()
resp.Close()
}
}
func BenchmarkPostRequest(b *testing.B) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("OK"))
}))
defer server.Close()
testData := []byte("test data for benchmark")
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
resp, err := Post(server.URL, WithBody(testData))
if err != nil {
b.Fatalf("Post() error: %v", err)
}
resp.Body().String()
resp.Close()
}
}
func BenchmarkJSONRequest(b *testing.B) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(`{"status":"ok"}`))
}))
defer server.Close()
type TestData struct {
Name string `json:"name"`
Value int `json:"value"`
}
data := TestData{Name: "test", Value: 123}
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
resp, err := Post(server.URL, WithJSON(data))
if err != nil {
b.Fatalf("Post() error: %v", err)
}
var result map[string]string
resp.Body().JSON(&result)
resp.Close()
}
}
func BenchmarkConcurrentRequests(b *testing.B) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("OK"))
}))
defer server.Close()
b.ResetTimer()
b.ReportAllocs()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
resp, err := Get(server.URL)
if err != nil {
b.Fatalf("Get() error: %v", err)
}
resp.Body().String()
resp.Close()
}
})
}
func BenchmarkRequestClone(b *testing.B) {
req := NewSimpleRequest("https://example.com", "GET").
SetHeader("X-Custom", "value").
AddQuery("key", "value")
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_ = req.Clone()
}
}
func BenchmarkClientCreation(b *testing.B) {
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_ = NewClientNoErr()
}
}
func BenchmarkRequestCreation(b *testing.B) {
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_ = NewSimpleRequest("https://example.com", "GET")
}
}
func BenchmarkRequestPrepareDefaultPath(b *testing.B) {
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
req := NewSimpleRequest("https://example.com", "GET")
if err := req.prepare(); err != nil {
b.Fatalf("prepare() error: %v", err)
}
}
}
func BenchmarkRequestPrepareDynamicPath(b *testing.B) {
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
req := NewSimpleRequest("https://example.com", "GET",
WithCustomIP([]string{"127.0.0.1"}),
WithSkipTLSVerify(true),
)
if err := req.prepare(); err != nil {
b.Fatalf("prepare() error: %v", err)
}
}
}
func BenchmarkResponseBodyRead(b *testing.B) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("test response data"))
}))
defer server.Close()
// Pre-fetch response
resp, _ := Get(server.URL, WithAutoFetch(true))
defer resp.Close()
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_, _ = resp.Body().String()
}
}
func BenchmarkDifferentResponseSizes(b *testing.B) {
sizes := []int{100, 1024, 10240, 102400} // 100B, 1KB, 10KB, 100KB
for _, size := range sizes {
responseData := make([]byte, size)
for i := 0; i < size; i++ {
responseData[i] = 'A'
}
b.Run(fmt.Sprintf("Size_%d", size), func(b *testing.B) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write(responseData)
}))
defer server.Close()
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
resp, err := Get(server.URL)
if err != nil {
b.Fatalf("Get() error: %v", err)
}
resp.Body().Bytes()
resp.Close()
}
})
}
}