chore: baseline snapshot before moderation-strictness feature
Repo .git was damaged (refs/ missing, index truncated, object store near-empty). Repaired via git init (rebuilt refs), stale index preserved as .git/index.corrupt-20260910.bak, then full worktree committed as a rollback baseline.
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
// Copyright 2026 tamakyi. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package conf
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"gopkg.in/ini.v1"
|
||||
)
|
||||
|
||||
// TestLimitsDefaults 保证内置默认值与旧版硬编码一致:未配置 [limits] 段(或 conf.Init
|
||||
// 尚未调用)时,程序按这些默认值运行。
|
||||
func TestLimitsDefaults(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
got int
|
||||
want int
|
||||
}{
|
||||
{"MaxTags", Limits.MaxTags, 5},
|
||||
{"MaxTagLen", Limits.MaxTagLen, 5},
|
||||
{"MaxBlockWords", Limits.MaxBlockWords, 10},
|
||||
{"MaxBlockWordLen", Limits.MaxBlockWordLen, 10},
|
||||
{"CustomAnswerLen", Limits.CustomAnswerLen, 200},
|
||||
{"VoteOptionLen", Limits.VoteOptionLen, 300},
|
||||
{"QuestionContentLen", Limits.QuestionContentLen, 1000},
|
||||
{"AnswerContentLen", Limits.AnswerContentLen, 2000},
|
||||
{"FollowUpContentLen", Limits.FollowUpContentLen, 2000},
|
||||
{"ChatMessageLen", Limits.ChatMessageLen, 2000},
|
||||
{"ChatMaxMessages", Limits.ChatMaxMessages, 200},
|
||||
{"DailyMessageLimitMax", Limits.DailyMessageLimitMax, 999},
|
||||
}
|
||||
for _, c := range cases {
|
||||
if c.got != c.want {
|
||||
t.Errorf("%s = %d, want %d", c.name, c.got, c.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestLimitsMapTo 模拟 conf.Init 的映射行为:显式键被覆盖,缺失键保留默认。
|
||||
// 启动逻辑是 File.Section("limits").MapTo(&Limits),与这里同一路径。
|
||||
func TestLimitsMapTo(t *testing.T) {
|
||||
src := `
|
||||
[limits]
|
||||
max_tags = 7
|
||||
chat_message_len = 500
|
||||
answer_content_len = 300
|
||||
daily_message_limit_max = 0
|
||||
`
|
||||
f, err := ini.LoadSources(ini.LoadOptions{IgnoreInlineComment: true}, []byte(src))
|
||||
if err != nil {
|
||||
t.Fatalf("parse ini: %v", err)
|
||||
}
|
||||
l := Limits // 拷贝默认值,等价于启动前状态
|
||||
if err := f.Section("limits").MapTo(&l); err != nil {
|
||||
t.Fatalf("map [limits]: %v", err)
|
||||
}
|
||||
if l.MaxTags != 7 {
|
||||
t.Errorf("MaxTags = %d, want 7 (ini 覆盖失败)", l.MaxTags)
|
||||
}
|
||||
if l.ChatMessageLen != 500 {
|
||||
t.Errorf("ChatMessageLen = %d, want 500", l.ChatMessageLen)
|
||||
}
|
||||
if l.AnswerContentLen != 300 {
|
||||
t.Errorf("AnswerContentLen = %d, want 300(ini 覆盖失败)", l.AnswerContentLen)
|
||||
}
|
||||
if l.DailyMessageLimitMax != 0 {
|
||||
t.Errorf("DailyMessageLimitMax = %d, want 0(配置为 0 应生效)", l.DailyMessageLimitMax)
|
||||
}
|
||||
// 未显式出现的键保留内置默认
|
||||
if l.MaxTagLen != 5 {
|
||||
t.Errorf("MaxTagLen = %d, want 5(缺失键应保留默认)", l.MaxTagLen)
|
||||
}
|
||||
if l.VoteOptionLen != 300 {
|
||||
t.Errorf("VoteOptionLen = %d, want 300", l.VoteOptionLen)
|
||||
}
|
||||
if l.QuestionContentLen != 1000 || l.FollowUpContentLen != 2000 {
|
||||
t.Errorf("QuestionContentLen/FollowUpContentLen = %d/%d, want 1000/2000(缺失键应保留默认)",
|
||||
l.QuestionContentLen, l.FollowUpContentLen)
|
||||
}
|
||||
}
|
||||
|
||||
// TestLimitsEmptyValueSanitized 验证「键留空」的防护:ini 会把空 int 解析为 0,
|
||||
// sanitizeLimits 随后将其回退到内置默认 —— 防止留空把上限静默置零(标签全拒等)。
|
||||
func TestLimitsEmptyValueSanitized(t *testing.T) {
|
||||
src := `
|
||||
[limits]
|
||||
max_tags =
|
||||
chat_message_len = 0
|
||||
followup_content_len = -1
|
||||
daily_message_limit_max = -3
|
||||
`
|
||||
f, err := ini.LoadSources(ini.LoadOptions{IgnoreInlineComment: true}, []byte(src))
|
||||
if err != nil {
|
||||
t.Fatalf("parse ini: %v", err)
|
||||
}
|
||||
l := Limits
|
||||
if err := f.Section("limits").MapTo(&l); err != nil {
|
||||
t.Fatalf("map [limits]: %v", err)
|
||||
}
|
||||
// 前提确认:空串对 int 是「保留原值」而非 0(gopkg.in/ini 行为);
|
||||
// 显式 0 / 负数则照常映射。真正的 0 陷阱来自显式填 0 / 负数,由 sanitize 兜底。
|
||||
if l.MaxTags != defaultMaxTags {
|
||||
t.Fatalf("precondition broken: 空值 max_tags 应保留默认, got %d", l.MaxTags)
|
||||
}
|
||||
if l.ChatMessageLen != 0 || l.DailyMessageLimitMax != -3 {
|
||||
t.Fatalf("precondition broken: got %d/%d, want 0/-3",
|
||||
l.ChatMessageLen, l.DailyMessageLimitMax)
|
||||
}
|
||||
sanitizeLimits(&l)
|
||||
if l.MaxTags != defaultMaxTags {
|
||||
t.Errorf("MaxTags = %d, want 默认 %d", l.MaxTags, defaultMaxTags)
|
||||
}
|
||||
if l.ChatMessageLen != defaultChatMessageLen {
|
||||
t.Errorf("ChatMessageLen = %d, want 默认 %d(0 应回退默认)", l.ChatMessageLen, defaultChatMessageLen)
|
||||
}
|
||||
if l.FollowUpContentLen != defaultFollowUpContentLen {
|
||||
t.Errorf("FollowUpContentLen = %d, want 默认 %d(负数应回退默认)", l.FollowUpContentLen, defaultFollowUpContentLen)
|
||||
}
|
||||
if l.DailyMessageLimitMax != defaultDailyMessageLimitMax {
|
||||
t.Errorf("DailyMessageLimitMax = %d, want 默认 %d(负数应回退默认)", l.DailyMessageLimitMax, defaultDailyMessageLimitMax)
|
||||
}
|
||||
if l.ChatMaxMessages != defaultChatMaxMessages {
|
||||
t.Errorf("ChatMaxMessages = %d, want 默认 %d(缺失键不受影响)", l.ChatMaxMessages, defaultChatMaxMessages)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user