Smail/backend/services/rule/match/regex_match_test.go
smail f60d3b0880
Some checks are pending
Security Checks / security (push) Waiting to run
整理前后端与测试构建目录并完善配置和安全引导
统一 frontend、backend、test、test-log 和 out 目录,更新构建、部署及测试入口;纳入配置管理兼容与首次安全引导修复;排除本机配置、密钥和测试产物。
2026-09-05 19:19:52 +08:00

73 lines
2.4 KiB
Go

package match
import (
"bytes"
"strings"
"testing"
"time"
"git.pcux.cn/xuans/Smail/dto/parsemail"
appcontext "git.pcux.cn/xuans/Smail/utils/context"
log "github.com/sirupsen/logrus"
)
func TestRegexMatch(t *testing.T) {
email := &parsemail.Email{Subject: "safe@example.com"}
if !NewRegexMatch("Subject", `^(?!.*blocked\.example$).*`).Match(&appcontext.Context{}, email) {
t.Fatal("valid regex did not match")
}
}
func TestRegexMatchRejectsInvalidPatternWithoutPanic(t *testing.T) {
email := &parsemail.Email{Subject: "subject"}
if NewRegexMatch("Subject", "(").Match(&appcontext.Context{}, email) {
t.Fatal("invalid regex matched")
}
}
func TestRegexMatchTimesOutCatastrophicBacktracking(t *testing.T) {
email := &parsemail.Email{Subject: strings.Repeat("a", 200000) + "!"}
var output bytes.Buffer
logger := log.StandardLogger()
oldOutput := logger.Out
logger.SetOutput(&output)
t.Cleanup(func() { logger.SetOutput(oldOutput) })
started := time.Now()
if NewRegexMatch("Subject", `^(a+)+$`).Match(&appcontext.Context{}, email) {
t.Fatal("catastrophic regex unexpectedly matched")
}
if elapsed := time.Since(started); elapsed > 2*time.Second {
t.Fatalf("regex timeout took too long: %s", elapsed)
}
if strings.Contains(output.String(), email.Subject) || output.Len() > 4096 {
t.Fatalf("regex failure leaked or amplified message content: log_bytes=%d", output.Len())
}
}
func TestValidateRegexRejectsOversizedPattern(t *testing.T) {
if err := ValidateRegex(strings.Repeat("a", maxRegexPatternBytes+1)); err == nil {
t.Fatal("oversized regex was accepted")
}
}
func TestRuleBodyMatchingIsSizeLimited(t *testing.T) {
email := &parsemail.Email{Text: []byte(strings.Repeat("a", maxRuleFieldBytes) + "needle")}
if NewContainsMatch("Text", "needle").Match(&appcontext.Context{}, email) {
t.Fatal("rule matched content beyond the field inspection limit")
}
email.Text = []byte("needle" + strings.Repeat("a", maxRuleFieldBytes))
if !NewContainsMatch("Text", "needle").Match(&appcontext.Context{}, email) {
t.Fatal("rule did not match content within the field inspection limit")
}
}
func TestGetFieldContentHandlesMissingAddresses(t *testing.T) {
email := &parsemail.Email{}
if got := getFieldContent("From", email); got != "" {
t.Fatalf("missing From returned %q", got)
}
if got := getFieldContent("Sender", email); got != "" {
t.Fatalf("missing Sender returned %q", got)
}
}