Documentation
¶
Overview ¶
Package fixtures 提供 go-reqx 测试体系下的"标准输入数据"。
设计原则:
一切"测试反复构造的 payload"都集中在这里,避免每个 _test.go 自己手写;
函数命名采用 BuildXxx / NewXxx 前缀: - BuildXxx 表示"在 TempTree 上构造副作用(写文件等)",需要 *testing.T; - NewXxx 表示"返回纯字节 / 结构体",不需要 *testing.T;
所有"超大"或"恶意"输入都带上明确的硬上限(通常 64MiB),避免本机自爆;
不引入第三方依赖;纯标准库。
与 testkit/fuzz 的关系:
- testkit/fuzz/seed.go 提供 fuzz 用的 corpus(变异输入);
- fixtures 提供"非 fuzz 的固定输入"(happy path / known-bad);
- 部分小型 corpus 在两者之间共享时,由 fixtures 暴露 const 切片,fuzz 引用。
Package fixtures —— gzip_bomb.go
构造"gzip bomb"字节:压缩前后比例巨大,常用于 client 解压上限的对抗测试。
安全约束:
- 解压后的最大尺寸由调用方传入;
- 内部硬限 64 MiB,避免单元测试机器自爆;
- 输入字节总是全 0(最高压缩比),保证一字节级别的 ratio 控制。
Package fixtures —— headers.go ¶
预制 HTTP Header 集合,覆盖:
- 通用 happy path;
- 含敏感字段(用于跨域 redirect 时是否被 client 正确丢弃的断言);
- 超大 header(验证 client 是否在编码侧合理截断或拒绝);
- 含 ASCII / 非 ASCII 混合(验证 sanitize 路径)。
Package fixtures —— json.go ¶
预制 JSON payload,覆盖三类场景:
- 合法 happy path:标准结构体序列化结果;
- 边界 / 极端:嵌套深、字段数多、大字符串;
- 不合法:常见的 JSON 解码错误样本,client 应当返回 err 而不是 panic。
这些 payload 被 fuzz / unit / integration 共享。
Package fixtures —— multipart.go ¶
在 helper.TempTree 上构造 multipart 测试用文件树。
用法:
tree := helper.NewTempTree(t)
mp := fixtures.BuildMultipartTree(t, tree, fixtures.MultipartSpec{
SmallTextFiles: 3,
BinaryFile: 1024 * 1024, // 1 MiB
EmptyFile: true,
})
// mp.SmallTexts / mp.Binary / mp.Empty 给出绝对路径,可直接传给
// rest.Request 的 multipart 上传 API。
Package fixtures —— redirect_loop.go
预制 redirect chain 输入,供 integration / security 测试反复使用。
不依赖 server:只暴露"我希望 server 返回的 Location 头序列", 由测试侧把它喂给 testkit/server.RedirectChainHandler 或自定义 handler。
Package fixtures —— streams.go ¶
io.Reader / io.ReadCloser 装饰器,模拟各种"非 happy path"读取行为:
- SlowReader:每次 Read 前 sleep 一段时间(模拟慢拨号 / 慢响应);
- EOFAfterReader:读够 N 字节后立即 EOF(模拟"声明的长度比实际短");
- ErrAfterReader:读够 N 字节后返回指定 err(模拟"读到一半网络断开");
- FlakyReader:按概率间歇性返回错误(模拟不稳定网络);
- LimitedReadCloser:io.LimitReader 的 ReadCloser 版本,附带 Closed 标志。
设计:
- 严格保持 io.Reader 协议——EOF 之后绝不再返回字节;
- 不让 Read 永远阻塞(SlowReader 仍然有 deadline 退化路径);
- 所有装饰器都暴露统一的 Closed() / Reset() 等观察接口。
Index ¶
- Constants
- func CommonHeaders() http.Header
- func DeeplyNestedJSON(depth int) []byte
- func GzipBomb(uncompressedSize int) []byte
- func GzipBombLarge() []byte
- func GzipBombMedium() []byte
- func GzipBombSmall() []byte
- func HugeJSONPayload(size int) []byte
- func LargeUserPayload() []byte
- func MalformedJSONSamples() [][]byte
- func MaliciousHeaders() http.Header
- func MaliciousLocations() []string
- func MergeHeaders(hs ...http.Header) http.Header
- func OversizedHeaders(valueSize int) http.Header
- func SensitiveHeaders() http.Header
- func SmallUserPayload() []byte
- func SmallUserPayloadString() string
- type EOFAfterReader
- type ErrAfterReader
- type FlakyReader
- type LargeUser
- type LimitedReadCloser
- type MultipartFiles
- type MultipartSpec
- type RedirectChain
- type SlowReader
- type SmallUser
Constants ¶
const MaxGzipBombUncompressed = 64 * 1024 * 1024
MaxGzipBombUncompressed 是单次构造允许的最大解压尺寸(字节)。
比这更大的请求会被钳到本值。
Variables ¶
This section is empty.
Functions ¶
func DeeplyNestedJSON ¶
DeeplyNestedJSON 返回一个深度为 depth 的嵌套 object JSON。
用于触发解析器栈深度路径;depth 上限 4096(再大的栈深度通常会让 Go 解析器自身报错)。
func GzipBomb ¶
GzipBomb 返回一个 gzip 流,解压后大约 uncompressedSize 字节。
实现:循环写 chunk(4 KiB 全 0)直到达到目标大小,再 Close。
输出尺寸非常小(几 KB 即可解压出几十 MB 的全 0),适合"测试 client 是否 在 maxInMemoryBody 处截断、是否在流式路径不无脑读完"的场景。
func GzipBombLarge ¶
func GzipBombLarge() []byte
GzipBombLarge 返回 32 MiB 解压尺寸的 bomb(默认上限以下)。
注意:此函数返回的字节流被 client 完整解压时会占用 ~32 MiB 内存; 仅在 RequireHeavy/RequireExtreme 路径上使用。
func GzipBombSmall ¶
func GzipBombSmall() []byte
GzipBombSmall 返回一份"经典示意"的 gzip bomb:约 1 MiB 解压尺寸。
适合作为 unit/security 测试的默认 bomb,不需要每次调用 GzipBomb(...)。
func HugeJSONPayload ¶
HugeJSONPayload 返回一份 size 字节左右的 JSON payload;用于流式解码或截断测试。
size <= 0 时返回空切片;size > 64 MiB 时硬限到 64 MiB(防止本机内存爆炸)。
结构形如:
{"items":[{"i":0,"msg":"line-0"},{"i":1,"msg":"line-1"},...]}
func LargeUserPayload ¶
func LargeUserPayload() []byte
LargeUserPayload 返回一份字段较多的 JSON 字节,bio 是 2 KiB 文本。
func MalformedJSONSamples ¶
func MalformedJSONSamples() [][]byte
MalformedJSONSamples 返回一组"明显不合法"的 JSON 字节切片。
client 在收到这些响应时必须返回 decoder error,而不是 panic / 阻塞。
func MaliciousHeaders ¶
MaliciousHeaders 返回一组"明显违规"的请求头:含 CRLF 注入、控制字符等。
client 应当在写入 wire 前拒绝这些值(go 1.7+ 的 net/http 会做 sanitize), 测试用于断言"客户端代码不被这些 header 触发崩溃"。
func MaliciousLocations ¶
func MaliciousLocations() []string
MaliciousLocations 返回一组"client 必须拒绝"的 Location 值。
client 应当在 Follow-Redirect 路径上对它们返回 err,而不是真的拨号过去。
func OversizedHeaders ¶
OversizedHeaders 返回一组单值极长的 headers,用于压力测试。
单 header value 长度由参数 valueSize 控制,硬上限 1 MiB。
func SensitiveHeaders ¶
SensitiveHeaders 返回一组含敏感字段的请求头。
用于:
- 跨域 redirect 时验证 client 是否正确丢弃 Authorization / Cookie;
- SSRF 防护是否正确不携带凭据。
func SmallUserPayloadString ¶
func SmallUserPayloadString() string
SmallUserPayloadString 是 SmallUserPayload 的字符串版本。
Types ¶
type EOFAfterReader ¶
type EOFAfterReader struct {
// contains filtered or unexported fields
}
EOFAfterReader 是一个"前 N 字节透明转发,之后立刻 EOF"的 reader。
func NewEOFAfter ¶
func NewEOFAfter(src io.Reader, n int64) *EOFAfterReader
NewEOFAfter 在前 n 字节透明转发 src 之后立刻返回 io.EOF。
当 src 自身在 n 字节前就已 EOF,EOFAfterReader 也会传递该 EOF。
type ErrAfterReader ¶
type ErrAfterReader struct {
// contains filtered or unexported fields
}
ErrAfterReader 与 EOFAfterReader 类似,但 N 字节后返回的是调用方指定的 err。
func NewErrAfter ¶
func NewErrAfter(src io.Reader, n int64, finalErr error) *ErrAfterReader
NewErrAfter 在前 n 字节透明转发后返回 finalErr。
finalErr 为 nil 时使用 io.ErrUnexpectedEOF。
type FlakyReader ¶
type FlakyReader struct {
// contains filtered or unexported fields
}
FlakyReader 按概率间歇性返回 err,模拟不稳定网络。
func NewFlakyReader ¶
NewFlakyReader 装饰 src,每次 Read 有 failProb 概率返回 failErr。
failProb 钳到 [0, 1];failErr 为 nil 时使用 io.ErrUnexpectedEOF。
seed 控制随机源;0 表示使用一个固定常量(确定可复现)。
type LargeUser ¶
type LargeUser struct {
ID int `json:"id"`
Name string `json:"name"`
Bio string `json:"bio"`
Tags []string `json:"tags"`
Metadata map[string]string `json:"metadata"`
}
LargeUser 是带很多字段、大字符串的 JSON 结构体,用于"中等 body"路径。
type LimitedReadCloser ¶
LimitedReadCloser 是 io.LimitReader 的 ReadCloser 版本,并带 Closed() 观察。
func NewLimitedReadCloser ¶
func NewLimitedReadCloser(r io.Reader, n int64) *LimitedReadCloser
NewLimitedReadCloser 限制最多读取 n 字节后返回 EOF;Close 时调用 closer.Close(若有)。
type MultipartFiles ¶
type MultipartFiles struct {
// SmallTexts 小文本文件绝对路径列表,长度 = MultipartSpec.SmallTextFiles。
SmallTexts []string
// Binary 二进制文件路径,未生成时为空字符串。
Binary string
// Empty 0 字节文件路径,未生成时为空字符串。
Empty string
// UnicodeName 非 ASCII 文件名的文本文件路径,未生成时为空字符串。
UnicodeName string
}
MultipartFiles 是 BuildMultipartTree 的返回结果。
func BuildMultipartTree ¶
func BuildMultipartTree(t testing.TB, tree *helper.TempTree, spec MultipartSpec) MultipartFiles
BuildMultipartTree 在 tree 下构造给定 spec 的文件集合。
失败一律 t.Fatalf;调用方拿到的 MultipartFiles 总是"已成功落盘"的。
type MultipartSpec ¶
type MultipartSpec struct {
// SmallTextFiles 表示要生成多少个小文本文件(每个 ~256 字节,递增内容)。
SmallTextFiles int
// BinaryFile 表示是否生成一个伪随机二进制文件,及其大小(字节)。0 表示不生成。
BinaryFile int
// EmptyFile=true 时生成一个 0 字节文件。
EmptyFile bool
// UnicodeFilename=true 时额外生成一个 UTF-8 文件名("文件_中文.txt"),
// 用于验证 multipart 编码中 filename 字段的处理。
UnicodeFilename bool
}
MultipartSpec 描述要构造的文件集合。
type RedirectChain ¶
type RedirectChain struct {
// Locations 是按顺序返回的 Location 头列表。
// 最后一项为空字符串时,表示链路在该步骤结束(200 响应)。
Locations []string
// Description 用于失败诊断。
Description string
}
RedirectChain 描述一组预制 redirect 链路。
func HostJumpRedirectChain ¶
func HostJumpRedirectChain(otherHostURL string) RedirectChain
HostJumpRedirectChain 返回一个"换 host"的链路,用于测试 cross-origin 重定向时 的 cookie / referrer 行为。
func LinearRedirectChain ¶
func LinearRedirectChain(n int) RedirectChain
LinearRedirectChain 返回一个 N 步 linear redirect chain。
/redirect/N → /redirect/N-1 → ... → /redirect/0 (200 done)
func ProtocolJumpRedirectChain ¶
func ProtocolJumpRedirectChain(httpsBase string) RedirectChain
ProtocolJumpRedirectChain 返回一个"http → https"的协议跳跃链路。
用于测试 client 在跨协议 redirect 时,是否正确处理 Authorization / Cookie 等敏感头。
func SelfLoopRedirectChain ¶
func SelfLoopRedirectChain() RedirectChain
SelfLoopRedirectChain 返回一个会"指向自己"的 redirect 链路。
用于测试 client 是否在死循环到达 max redirects 后正确报错。
type SlowReader ¶
type SlowReader struct {
// contains filtered or unexported fields
}
SlowReader 在每次 Read 前 sleep 一段时间。
用于:
- 验证 ReadTimeout / 整体 timeout 的客户端行为;
- 触发 ResponseHeaderTimeout / streaming backpressure。
func NewSlowReader ¶
func NewSlowReader(src io.Reader, delay time.Duration) *SlowReader
NewSlowReader 装饰 src,每次 Read 前 sleep delay。
delay <= 0 时退化为透明转发。
func (*SlowReader) Close ¶
func (r *SlowReader) Close() error
Close 实现 io.Closer。后续 Read 立即返回 ErrClosedPipe。