180 lines
3.9 KiB
Go
180 lines
3.9 KiB
Go
// 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()
|
|
}
|
|
}
|