// Package testutil provides mock backends and test helpers. package testutil import ( "net" "time" "github.com/valyala/fasthttp" ) // 预定义的测试数据大小常量 const ( // Size100B 100 字节测试数据。 Size100B = 100 // Size1KB 1KB 测试数据。 Size1KB = 1024 // Size10KB 10KB 测试数据。 Size10KB = 10 * 1024 // Size100KB 100KB 测试数据。 Size100KB = 100 * 1024 // Size1MB 1MB 测试数据。 Size1MB = 1024 * 1024 ) // MockBackendConfig Mock 后端配置。 type MockBackendConfig struct { Mode string StatusCode int ResponseBody []byte ErrorRate float64 Delay time.Duration } // Mock 后端运行模式 const ( // ModeNormalResponse 正常响应模式。 ModeNormalResponse = "normal" // ModeRandomResponse 随机响应模式。 ModeRandomResponse = "random" // ModeErrorResponse 错误响应模式。 ModeErrorResponse = "error" // ModeDelayedResponse 延迟响应模式。 ModeDelayedResponse = "delayed" ) // GenerateTestData 生成指定大小的测试数据。 func GenerateTestData(size int) []byte { data := make([]byte, size) for i := range data { data[i] = byte(i % 256) } return data } // SimpleMockBackend 创建一个简单的 Mock HTTP 后端。 func SimpleMockBackend(statusCode int, responseBody []byte) (string, func()) { ln, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { panic(err) } handler := func(ctx *fasthttp.RequestCtx) { ctx.SetStatusCode(statusCode) ctx.SetBody(responseBody) } go func() { if serveErr := fasthttp.Serve(ln, handler); serveErr != nil { panic(serveErr) } }() return ln.Addr().String(), func() { _ = ln.Close() } } // ErrorMockBackend 创建一个返回错误的 Mock HTTP 后端。 func ErrorMockBackend(errorRate float64, errorBody []byte) (string, func()) { ln, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { panic(err) } var requestCount int handler := func(ctx *fasthttp.RequestCtx) { requestCount++ if float64(requestCount%100)/100 < errorRate { ctx.SetStatusCode(fasthttp.StatusInternalServerError) ctx.SetBody(errorBody) return } ctx.SetStatusCode(fasthttp.StatusOK) ctx.SetBody([]byte("OK")) } go func() { if serveErr := fasthttp.Serve(ln, handler); serveErr != nil { panic(serveErr) } }() return ln.Addr().String(), func() { _ = ln.Close() } } // DelayedMockBackend 创建一个有延迟的 Mock HTTP 后端。 func DelayedMockBackend(delay time.Duration, statusCode int, responseBody []byte) (string, func()) { ln, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { panic(err) } handler := func(ctx *fasthttp.RequestCtx) { time.Sleep(delay) ctx.SetStatusCode(statusCode) ctx.SetBody(responseBody) } go func() { if serveErr := fasthttp.Serve(ln, handler); serveErr != nil { panic(serveErr) } }() return ln.Addr().String(), func() { _ = ln.Close() } } // StartMockFasthttpBackend 创建一个可配置的 Mock HTTP 后端。 func StartMockFasthttpBackend(cfg MockBackendConfig) (string, func()) { ln, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { panic(err) } var requestCount int handler := func(ctx *fasthttp.RequestCtx) { requestCount++ if cfg.Delay > 0 { time.Sleep(cfg.Delay) } switch cfg.Mode { case ModeErrorResponse: if float64(requestCount%100)/100 < cfg.ErrorRate { ctx.SetStatusCode(fasthttp.StatusInternalServerError) ctx.SetBody(cfg.ResponseBody) return } case ModeDelayedResponse: time.Sleep(cfg.Delay) case ModeRandomResponse: if requestCount%2 == 0 { ctx.SetStatusCode(fasthttp.StatusOK) } else { ctx.SetStatusCode(fasthttp.StatusInternalServerError) } ctx.SetBody(cfg.ResponseBody) return } ctx.SetStatusCode(cfg.StatusCode) ctx.SetBody(cfg.ResponseBody) } go func() { if serveErr := fasthttp.Serve(ln, handler); serveErr != nil { panic(serveErr) } }() return ln.Addr().String(), func() { _ = ln.Close() } }