Files
AskaEth 4a2d276881
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
feat(capability): 转码能力包(vendor 纯 Go AMR-NB 解码器 + 黄金向量逐样本对照 + 8 哨兵 + 注册面)
2026-10-05 13:02:28 +08:00

68 lines
2.3 KiB
Go

package transcode
import (
"errors"
"strings"
"testing"
)
// TestSentinelInventoryMatchesDesign 把 design/25 §2.4 的**八个**哨兵钉在测试里:
// 少一个、多一个、或者文案离开 `transcode: ` 前缀都会红。它是「清单型断言」——
// 与只测边界逻辑互补(design/25 §6.3 的同一手法)。
func TestSentinelInventoryMatchesDesign(t *testing.T) {
designSentinels := []struct {
name string
err error
}{
{"ErrUnsupportedFormat", ErrUnsupportedFormat},
{"ErrInputTooLarge", ErrInputTooLarge},
{"ErrOutputTooLarge", ErrOutputTooLarge},
{"ErrDecodeFailed", ErrDecodeFailed},
{"ErrEncodeFailed", ErrEncodeFailed},
{"ErrTimeout", ErrTimeout},
{"ErrBusy", ErrBusy},
{"ErrNoBackend", ErrNoBackend},
}
if len(designSentinels) != 8 {
t.Fatalf("design/25 §2.4 是八个哨兵,这里列了 %d 个", len(designSentinels))
}
const prefix = "transcode: "
for _, s := range designSentinels {
if s.err == nil {
t.Fatalf("%s is nil", s.name)
}
if !strings.HasPrefix(s.err.Error(), prefix) {
t.Errorf("%s = %q, want the %q prefix", s.name, s.err.Error(), prefix)
}
if !isSentinelError(s.err) {
t.Errorf("%s is missing from knownErrors", s.name)
}
}
// 两两不同(防止复制粘贴出的同一个值被当成两个哨兵)。
for i := range designSentinels {
for j := i + 1; j < len(designSentinels); j++ {
if errors.Is(designSentinels[i].err, designSentinels[j].err) {
t.Errorf("%s and %s are the same error", designSentinels[i].name, designSentinels[j].name)
}
}
}
// 包内自有的构造期/入参错误也必须可见(它们不是 §2.4 的八个)。
for _, s := range []error{ErrDuplicate, ErrInvalidCodec, ErrBadArgs} {
if !isSentinelError(s) {
t.Errorf("%q is missing from knownErrors", s)
}
}
}
// TestTimeoutErrorKeepsBothCauses 断言超时错误同时能被判为 ErrTimeout、也保留
// 原始 ctx 原因(%w 链):调用方既能走哨兵分支,也能看到「为什么」。
func TestTimeoutErrorKeepsBothCauses(t *testing.T) {
err := timeoutError(errTimeoutCause)
if !errors.Is(err, ErrTimeout) || !errors.Is(err, errTimeoutCause) {
t.Fatalf("err = %v, want both ErrTimeout and the cause", err)
}
}
// errTimeoutCause 是超时链里的原始原因桩。
var errTimeoutCause = errors.New("stub deadline")